from django.conf import settings from django.core.exceptions import MiddlewareNotUsed from django.test import RequestFactory, SimpleTestCase, override_settings from . import middleware as mw @override_settings(ROOT_URLCONF='middleware_exceptions.urls') class MiddlewareTests(SimpleTestCase): def tearDown(self): mw.log = [] @override_settings(MIDDLEWARE=['middleware_exceptions.middleware.ProcessViewNoneMiddleware']) def test_process_view_return_none(self): response = self.client.get('/middleware_exceptions/view/') self.assertEqual(mw.log, ['processed view normal_view']) self.assertEqual(response.content, b'OK') @override_settings(MIDDLEWARE=['middleware_exceptions.middleware.ProcessViewMiddleware']) def test_process_view_return_response(self): response = self.client.get('/middleware_exceptions/view/') self.assertEqual(response.content, b'Processed view normal_view') @override_settings(MIDDLEWARE=[ 'middleware_exceptions.middleware.ProcessViewTemplateResponseMiddleware', 'middleware_exceptions.middleware.LogMiddleware', ]) def test_templateresponse_from_process_view_rendered(self): """ TemplateResponses returned from process_view() must be rendered before being passed to any middleware that tries to access response.content, such as middleware_exceptions.middleware.LogMiddleware. """ response = self.client.get('/middleware_exceptions/view/') self.assertEqual(response.content, b'Processed view normal_view\nProcessViewTemplateResponseMiddleware') @override_settings(MIDDLEWARE=[ 'middleware_exceptions.middleware.ProcessViewTemplateResponseMiddleware', 'middleware_exceptions.middleware.TemplateResponseMiddleware', ]) def test_templateresponse_from_process_view_passed_to_process_template_response(self): """ TemplateResponses returned from process_view() should be passed to any template response middleware. """ response = self.client.get('/middleware_exceptions/view/') expected_lines = [ b'Processed view normal_view', b'ProcessViewTemplateResponseMiddleware', b'TemplateResponseMiddleware', ] self.assertEqual(response.content, b'\n'.join(expected_lines)) @override_settings(MIDDLEWARE=['middleware_exceptions.middleware.TemplateResponseMiddleware']) def test_process_template_response(self): response = self.client.get('/middleware_exceptions/template_response/') self.assertEqual(response.content, b'template_response OK\nTemplateResponseMiddleware') @override_settings(MIDDLEWARE=['middleware_exceptions.middleware.NoTemplateResponseMiddleware']) def test_process_template_response_returns_none(self): msg = ( "NoTemplateResponseMiddleware.process_template_response didn't " "return an HttpResponse object. It returned None instead." ) with self.assertRaisesMessage(ValueError, msg): self.client.get('/middleware_exceptions/template_response/') @override_settings(MIDDLEWARE=['middleware_exceptions.middleware.LogMiddleware']) def test_view_exception_converted_before_middleware(self): response = self.client.get('/middleware_exceptions/permission_denied/') self.assertEqual(mw.log, [(response.status_code, response.content)]) self.assertEqual(response.status_code, 403) @override_settings(MIDDLEWARE=['middleware_exceptions.middleware.ProcessExceptionMiddleware']) def test_view_exception_handled_by_process_exception(self): response = self.client.get('/middleware_exceptions/error/') self.assertEqual(response.content, b'Exception caught') @override_settings(MIDDLEWARE=[ 'middleware_exceptions.middleware.ProcessExceptionLogMiddleware', 'middleware_exceptions.middleware.ProcessExceptionMiddleware', ]) def test_response_from_process_exception_short_circuits_remainder(self): response = self.client.get('/middleware_exceptions/error/') self.assertEqual(mw.log, []) self.assertEqual(response.content, b'Exception caught') @override_settings(MIDDLEWARE=[ 'middleware_exceptions.middleware.LogMiddleware', 'middleware_exceptions.middleware.NotFoundMiddleware', ]) def test_exception_in_middleware_converted_before_prior_middleware(self): response = self.client.get('/middleware_exceptions/view/') self.assertEqual(mw.log, [(404, response.content)]) self.assertEqual(response.status_code, 404) @override_settings(MIDDLEWARE=['middleware_exceptions.middleware.ProcessExceptionMiddleware']) def test_exception_in_render_passed_to_process_exception(self): response = self.client.get('/middleware_exceptions/exception_in_render/') self.assertEqual(response.content, b'Exception caught') @override_settings(ROOT_URLCONF='middleware_exceptions.urls') class RootUrlconfTests(SimpleTestCase): @override_settings(ROOT_URLCONF=None) def test_missing_root_urlconf(self): # Removing ROOT_URLCONF is safe, as override_settings will restore # the previously defined settings. del settings.ROOT_URLCONF with self.assertRaises(AttributeError): self.client.get("/middleware_exceptions/view/") class MyMiddleware: def __init__(self, get_response=None): raise MiddlewareNotUsed def process_request(self, request): pass class MyMiddlewareWithExceptionMessage: def __init__(self, get_response=None): raise MiddlewareNotUsed('spam eggs') def process_request(self, request): pass @override_settings( DEBUG=True, ROOT_URLCONF='middleware_exceptions.urls', MIDDLEWARE=['django.middleware.common.CommonMiddleware'], ) class MiddlewareNotUsedTests(SimpleTestCase): rf = RequestFactory() def test_raise_exception(self): request = self.rf.get('middleware_exceptions/view/') with self.assertRaises(MiddlewareNotUsed): MyMiddleware().process_request(request) @override_settings(MIDDLEWARE=['middleware_exceptions.tests.MyMiddleware']) def test_log(self): with self.assertLogs('django.request', 'DEBUG') as cm: self.client.get('/middleware_exceptions/view/') self.assertEqual( cm.records[0].getMessage(), "MiddlewareNotUsed: 'middleware_exceptions.tests.MyMiddleware'" ) @override_settings(MIDDLEWARE=['middleware_exceptions.tests.MyMiddlewareWithExceptionMessage']) def test_log_custom_message(self): with self.assertLogs('django.request', 'DEBUG') as cm: self.client.get('/middleware_exceptions/view/') self.assertEqual( cm.records[0].getMessage(), "MiddlewareNotUsed('middleware_exceptions.tests.MyMiddlewareWithExceptionMessage'): spam eggs" ) @override_settings(DEBUG=False) def test_do_not_log_when_debug_is_false(self): with self.assertRaisesMessage(AssertionError, 'no logs'): with self.assertLogs('django.request', 'DEBUG'): self.client.get('/middleware_exceptions/view/')