Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django test: TransactionManagementError: You can't execute queries until the end of the 'atomic' block

Django newbie here. I'm trying to implement unit tests for a simple API I developed. Below you can find my test implementation which works fine:

from django.test import TestCase
from my_app.models import MyModel


class TestMyViewSet(TestCase):
    """
    Unit tests for endpoints in MyViewSet.
    """
    fixtures = ['my_app/fixtures/data.yaml']

    def setUp(self):
        # Making setup for the test case here.


    def test_post_my_resource(self):

        # Checking that fixture is loaded correctly.
        self.assertEqual(MyModel.objects.all().count(),1)

        request_body = {
            'my_resource': "input_for_my_resource"
        }

        response = self.client.post('/my_resources/', data=request_body)
        self.assertEqual(response.status_code, 201)
        # self.assertEqual(MyModel.objects.all().count(),2)

But when I removed the last line self.assertEqual(MyModel.objects.all().count(),2) from the comment to test that my_resource is created successfully on the corresponding model by checking the number of instances, I got an error stating the following:

TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block.

What am I missing here?

Thanks in advance!

PS: I come across the following question: TransactionManagementError “You can't execute queries until the end of the 'atomic' block” while using signals, but only during Unit Testing but I'm not sure what's happening in my case is the same.

like image 971
hnroot Avatar asked May 15 '17 11:05

hnroot


1 Answers

Apparently, moving from django.test.TestCase to django.test.TransactionTestCase solved the issue. Here are some important points regarding the differences between django.test.TestCase and django.test.TransactionTestCase:

TransactionTestCase and TestCase are identical except for the manner in which the database is reset to a known state and the ability for test code to test the effects of commit and rollback:

  • TransactionTestCase resets the database after the test runs by truncating all tables. A TransactionTestCase may call commit and rollback and observe the effects of these calls on the database.

  • A TestCase, on the other hand, does not truncate tables after a test. Instead, it encloses the test code in a database transaction that is rolled back at the end of the test. This guarantees that the rollback at the end of the test restores the database to its initial state.

Here you can find more details from the docs TransactionTestCase

like image 200
hnroot Avatar answered Sep 21 '22 16:09

hnroot