Commit 0abb0693 authored by Adam Chainz's avatar Adam Chainz Committed by Tim Graham
Browse files

Fixed #25176 -- Prevented TestCase.setUpTestData() exception from leaking transaction.

parent f4afa699
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -1017,7 +1017,11 @@ class TestCase(TransactionTestCase):
                    except Exception:
                        cls._rollback_atomics(cls.cls_atomics)
                        raise
        try:
            cls.setUpTestData()
        except Exception:
            cls._rollback_atomics(cls.cls_atomics)
            raise

    @classmethod
    def tearDownClass(cls):
+3 −0
Original line number Diff line number Diff line
@@ -18,3 +18,6 @@ Bugfixes
* Fixed ``QuerySet.raw()`` so ``InvalidQuery`` is not raised when using the
  ``db_column`` name of a ``ForeignKey`` field with ``primary_key=True``
  (:ticket:`12768`).

* Prevented an exception in ``TestCase.setUpTestData()`` from leaking the
  transaction (:ticket:`25176`).
+33 −0
Original line number Diff line number Diff line
@@ -944,6 +944,39 @@ class OverrideSettingsTests(SimpleTestCase):
            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)


class DisallowedDatabaseQueriesTests(SimpleTestCase):
    def test_disallowed_database_queries(self):
        expected_message = (