|
1 | 1 | from functools import partial
|
2 | 2 |
|
| 3 | +try: |
| 4 | + from unittest.mock import Mock |
| 5 | +except ImportError: |
| 6 | + from mock import Mock |
| 7 | + |
| 8 | +from django.core.signals import request_finished, request_started |
3 | 9 | from django.contrib.auth.forms import AuthenticationForm
|
4 | 10 | from django.contrib.auth.models import User
|
5 |
| -from django.test import TestCase |
| 11 | +from django.test import SimpleTestCase, TestCase |
6 | 12 |
|
7 | 13 | from trac.test import EnvironmentStub, MockRequest
|
8 | 14 | from trac.web.api import RequestDone
|
9 | 15 | from trac.web.main import RequestDispatcher
|
10 | 16 |
|
| 17 | +from tracdjangoplugin.middlewares import DjangoDBManagementMiddleware |
11 | 18 | from tracdjangoplugin.plugins import PlainLoginComponent
|
12 | 19 |
|
13 | 20 |
|
@@ -127,3 +134,53 @@ def test_login_invalid_username_uppercased(self):
|
127 | 134 | def test_login_invalid_inactive_user(self):
|
128 | 135 | User.objects.create_user(username="test", password="test", is_active=False)
|
129 | 136 | self.assertLoginFails(username="test", password="test")
|
| 137 | + |
| 138 | + |
| 139 | +class DjangoDBManagementMiddlewareTestCase(SimpleTestCase): |
| 140 | + @classmethod |
| 141 | + def setUpClass(cls): |
| 142 | + # Remove receivers from the request_started and request_finished signals, |
| 143 | + # replacing them with a mock object so we can still check if they were called. |
| 144 | + super(DjangoDBManagementMiddlewareTestCase, cls).setUpClass() |
| 145 | + cls._original_signal_receivers = {} |
| 146 | + cls.signals = {} |
| 147 | + for signal in [request_started, request_finished]: |
| 148 | + cls.signals[signal] = Mock() |
| 149 | + cls._original_signal_receivers[signal] = signal.receivers |
| 150 | + signal.receivers = [] |
| 151 | + signal.connect(cls.signals[signal]) |
| 152 | + |
| 153 | + @classmethod |
| 154 | + def tearDownClass(cls): |
| 155 | + # Restore the signals we modified in setUpClass() to what they were before |
| 156 | + super(DjangoDBManagementMiddlewareTestCase, cls).tearDownClass() |
| 157 | + for signal, original_receivers in cls._original_signal_receivers.items(): |
| 158 | + # messing about with receivers directly is not an official API, so we need to |
| 159 | + # call some undocumented methods to make sure caches and such are taken care of. |
| 160 | + with signal.lock: |
| 161 | + signal.receivers = original_receivers |
| 162 | + signal._clear_dead_receivers() |
| 163 | + signal.sender_receivers_cache.clear() |
| 164 | + |
| 165 | + def setUp(self): |
| 166 | + super(DjangoDBManagementMiddlewareTestCase, self).setUp() |
| 167 | + for mockobj in self.signals.values(): |
| 168 | + mockobj.reset_mock() |
| 169 | + |
| 170 | + def test_request_start_fired(self): |
| 171 | + app = DjangoDBManagementMiddleware(lambda environ, start_response: [b"test"]) |
| 172 | + output = b"".join(app(None, None)) |
| 173 | + self.assertEqual(output, b"test") |
| 174 | + self.signals[request_started].assert_called_once() |
| 175 | + |
| 176 | + def test_request_finished_fired(self): |
| 177 | + app = DjangoDBManagementMiddleware(lambda environ, start_response: [b"test"]) |
| 178 | + output = b"".join(app(None, None)) |
| 179 | + self.assertEqual(output, b"test") |
| 180 | + self.signals[request_finished].assert_called_once() |
| 181 | + |
| 182 | + def test_request_finished_fired_even_with_error(self): |
| 183 | + app = DjangoDBManagementMiddleware(lambda environ, start_response: [1 / 0]) |
| 184 | + with self.assertRaises(ZeroDivisionError): |
| 185 | + list(app(None, None)) |
| 186 | + self.signals[request_finished].assert_called_once() |
0 commit comments