Django unit test client response has empty context

2019-02-21 14:43发布

I have a unit test that's failing in an assertion that passes in another test in the same test case class.

Here's the passing test:

def test_home(self):
    c = Client()
    resp = c.get('/')
    self.assertEqual(resp.status_code, 200)
    self.assertTrue('a_formset' in resp.context)

Here's the failing test:

def test_number_initial_number_of_forms(self):
    c = Client()
    resp = c.get('/')
    self.assertEqual(resp.context['a_formset'].total_form_count(), 1)

In the second test, I get the error TypeError: 'NoneType' object has no attribute '__getitem__'.

If I execute the second test as

def test_number_initial_number_of_forms(self):
    c = Client()
    resp = c.get('/')
    self.assertTrue('a_formset' in resp.context)
    self.assertEqual(resp.context['a_formset'].total_form_count(), 1)

I get the error TypeError: argument of type 'NoneType' is not iterable. I've confirmed via print statements in the second test that the response.content contains the page I expect to get, that the status code is correct, and that the template is correct. But the response's context is consistently None in the second test.

I'm running my Django unit tests through the standard "python manage.py test ..." interface, so I don't believe I'm running into the "context is empty from the shell" issue.

What's going on with this?

Edit:

If I add print type(resp.context['a_formset']) to each test, for the working test I get <class 'django.forms.formsets.AFormFormSet'>. For the non-working test, I get TypeError: 'NoneType' object has no attribute '__getitem__' again.

2条回答
混吃等死
2楼-- · 2019-02-21 15:06

It's because you ran into some error, exited the shell and restarted it.

But you forgot to start environment...

from django.test.utils import setup_test_environment
>>> setup_test_environment()

That was my problem. Hope it works...

查看更多
Ridiculous、
3楼-- · 2019-02-21 15:24

Today I run into the same issue. The second test gets same page has nothing in response.context

I made a research and found that 1) test client uses signals to populate context, 2) my view method is not called for the second test

I turned on a debugger and found that the guilty one is 'Cache middleware'. Knowing that I found this ticket and this SO question (the latter has a solution).

So, in short: the second request is served from cache, not from a view, thus a view is not executed and test-client doesn't get the signal and have no ability to populate context.

I can not disable cache middleware for my project, so I added next hack-lines into my settings:

if 'test' in sys.argv:
   CACHE_MIDDLEWARE_SECONDS = 0

Hope this helps someone

查看更多
登录 后发表回答