Reputation: 8361
I'm trying to write a test that validates HTML returned from a generic class-based view. Let's say I have this function-based view that simply renders a template:
# views.py
from django.shortcuts import render
def simple_view(request, template='template.html'):
return render(request, template)
With that, during testing I can just do:
# tests.py
from django.http import HttpRequest
from .views import simple_view
request = HttpRequest()
response = simple_view(request)
and then do the validation on the response
. Now I would like to convert the above to a class-based view inheriting from TemplateView:
# views.py
from django.views.generic import TemplateView
class SimpleView(TemplateView):
template_name = 'template.html'
Now essentially the same testing method fails:
# tests.py
from django.http import HttpRequest
from .views import SimpleView
request = HttpRequest()
view_func = SimpleView.as_view()
response = view_func(request).render()
results in
Traceback (most recent call last):
File "tests.py", line 30, in test_home_page_returns_correct_html
response = view_func(request).render()
File "lib/python2.7/site-packages/django/views/generic/base.py", line 68, in view
return self.dispatch(request, *args, **kwargs)
File "lib/python2.7/site-packages/django/views/generic/base.py", line 82, in dispatch
if request.method.lower() in self.http_method_names:
AttributeError: 'NoneType' object has no attribute 'lower'
I've tried setting request.method
manually to GET
, but that just brings up another error complaining about session
not being in request
.
Is there a way of getting a response from TemplateView with "empty" request?
Upvotes: 6
Views: 3009
Reputation: 8361
Thanks dm03513 for the pointers! Indeed I had to use RequestFactory, but also make sure that request
contains an empty session
(despite SessionMiddleware
being listed first):
# tests.py
from django.test import TestCase
from django.test.client import RequestFactory
class SimpleTest(TestCase):
def setUp(self):
self.factory = RequestFactory()
def test_home_page_returns_correct_html(self):
request = self.factory.get('/')
request.session = {}
view_func = SimpleView.as_view()
response = view_func(request)
response.render()
self.assertIn('<html>', response.content)
Upvotes: 6
Reputation: 55962
You could use djangos built in test client to accomplish this, instead of instantiating and calling view directly
test client allows you to make a request through django url router
response = self.get('/url/to/invoke/simpleview/')
additionally there are a couple blogposts I found touching on how to test class based views, one of which is http://tech.novapost.fr/django-unit-test-your-views-en.html
Upvotes: 2