[1.8.x] Fixed #25176 -- Prevented TestCase.setUpTestData() exception from leaking transaction.

Backport of 0abb06930f from master
This commit is contained in:
Adam Chainz 2015-07-26 17:42:21 +01:00 committed by Tim Graham
parent 1acdb88136
commit b46dad1bef
3 changed files with 41 additions and 1 deletions

View File

@ -958,7 +958,11 @@ class TestCase(TransactionTestCase):
except Exception: except Exception:
cls._rollback_atomics(cls.cls_atomics) cls._rollback_atomics(cls.cls_atomics)
raise raise
cls.setUpTestData() try:
cls.setUpTestData()
except Exception:
cls._rollback_atomics(cls.cls_atomics)
raise
@classmethod @classmethod
def tearDownClass(cls): def tearDownClass(cls):

View File

@ -18,3 +18,6 @@ Bugfixes
* Fixed ``QuerySet.raw()`` so ``InvalidQuery`` is not raised when using the * Fixed ``QuerySet.raw()`` so ``InvalidQuery`` is not raised when using the
``db_column`` name of a ``ForeignKey`` field with ``primary_key=True`` ``db_column`` name of a ``ForeignKey`` field with ``primary_key=True``
(:ticket:`12768`). (:ticket:`12768`).
* Prevented an exception in ``TestCase.setUpTestData()`` from leaking the
transaction (:ticket:`25176`).

View File

@ -914,3 +914,36 @@ class OverrideSettingsTests(TestCase):
with self.settings(STATICFILES_DIRS=[test_path]): with self.settings(STATICFILES_DIRS=[test_path]):
finder = get_finder('django.contrib.staticfiles.finders.FileSystemFinder') finder = get_finder('django.contrib.staticfiles.finders.FileSystemFinder')
self.assertIn(expected_location, finder.locations) self.assertIn(expected_location, finder.locations)
class TestBadSetUpTestData(TestCase):
"""
An exception in setUpTestData() shouldn't leak a transaction which would
cascade across the rest of the test suite.
"""
class MyException(Exception):
pass
@classmethod
def setUpClass(cls):
try:
super(TestBadSetUpTestData, cls).setUpClass()
except cls.MyException:
cls._in_atomic_block = connection.in_atomic_block
@classmethod
def tearDownClass(Cls):
# override to avoid a second cls._rollback_atomics() which would fail.
# Normal setUpClass() methods won't have exception handling so this
# method wouldn't typically be run.
pass
@classmethod
def setUpTestData(cls):
# Simulate a broken setUpTestData() method.
raise cls.MyException()
def test_failure_in_setUpTestData_should_rollback_transaction(self):
# setUpTestData() should call _rollback_atomics() so that the
# transaction doesn't leak.
self.assertFalse(self._in_atomic_block)