0

this is the test that broke:

def test_registering_user_twice_cause_error_msg(self):

    user=User(name='pyRock',email='python@rocks.com')
    user.save()

    #create the request used to test the view
    self.request.session = {}
    self.request.method = 'POST'
    self.request.POST = {
        'email':'python@rocks.com',
        'name':'pyRock',
        'stripe_token':'...',
        'last_4_digits':'4242',
        'password':'bad_password',
        'ver_password':'bad_password'
    }

    expected_form=UserForm(self.request.POST)
    expected_form.is_valid()
    expected_form.addError('python@rocks.com is already a member')

    #create the expected html
    html = render_to_response(
        'register.html',
        {
            'form': expected_form,
            'months': range(1, 12),
            'publishable': settings.STRIPE_PUBLISHABLE,
            'soon': soon(),
            'user': None,
            'years': list(range(2011, 2036)),
        }
    )

    #mock out stripe so we don't hit their server
    with mock.patch('stripe.Customer') as stripe_mock:

        config = {'create.return_value': mock.Mock()}
        stripe_mock.configure_mock(**config)

        #run the test
        resp = register(self.request)

        #verify that we did things correctly

        self.assertEqual(resp.status_code, 200)
        self.assertEqual(self.request.session, {})
        self.assertEqual(resp.content, html.content)

        #assert there is no records in the database.
        users = User.objects.filter(email="python@rocks.com")
        self.assertEqual(len(users), 1)

So when running the test it throws the following:

ERROR: test_registering_user_twice_cause_error_msg (payments.tests.RegisterPageTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/1111/_realpython/d3/django_ecommerce/payments/tests.py", line 278, in test_registering_user_twice_cause_error_msg
    self.assertEqual(len(users), 1)
  File "/Users/1111/.virtualenvs/d317/lib/python2.7/site-packages/django/db/models/query.py", line 122, in __len__
    self._fetch_all()
  File "/Users/1111/.virtualenvs/d317/lib/python2.7/site-packages/django/db/models/query.py", line 966, in _fetch_all
    self._result_cache = list(self.iterator())
  File "/Users/1111/.virtualenvs/d317/lib/python2.7/site-packages/django/db/models/query.py", line 265, in iterator
    for row in compiler.results_iter():
  File "/Users/1111/.virtualenvs/d317/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 700, in results_iter
    for rows in self.execute_sql(MULTI):
  File "/Users/1111/.virtualenvs/d317/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 786, in execute_sql
    cursor.execute(sql, params)
  File "/Users/1111/.virtualenvs/d317/lib/python2.7/site-packages/django/db/backends/utils.py", line 59, in execute
    self.db.validate_no_broken_transaction()
  File "/Users/1111/.virtualenvs/d317/lib/python2.7/site-packages/django/db/backends/__init__.py", line 386, in validate_no_broken_transaction
    "An error occurred in the current transaction. You can't "
TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block.

I read a couple answers about Django wrapping up each test in a transaction, but I can't make anything out of it as I am a Django noob, and the code above is the tutorial.

It's even more interesting that the exception happens in the assertion. If I remove it the test passes, even with the query users = User.objects.filter(email="python@rocks.com") present. However, if I reference users in some way, say just print users the test breaks again.

So what's going on?

Thanks!

kurtgn
  • 8,140
  • 13
  • 55
  • 91
  • possible duplicate of [TransactionManagementError "You can't execute queries until the end of the 'atomic' block" while using signals, but only during Unit Testing](http://stackoverflow.com/questions/21458387/transactionmanagementerror-you-cant-execute-queries-until-the-end-of-the-atom) – Makoto Feb 16 '15 at 03:42

1 Answers1

0

So what's going on?

As stated, this is a duplicate.

But I'll separately address the reason it breaks if you access users. The reason this happens is that Django database calls are lazy and delays execution until you finally use query.

So if you never use or iterate through users it will save you a database call. This is why it looked like it was working, was because if you remove len(users) it never needs the result of users,so won't query for it.

Community
  • 1
  • 1