Reputation: 109
I want to test some views in DRF project.
The problem comes when I try to check views that have arguments in the urls.
urls.py
url(r'^(?Pcompany_hash>[\d\w]+)/(?Ptimestamp>[\.\d]*)/employees/$', EmployeeList.as_view(), name='employeelist'),
[edit: "<" in url has been deleted in purpose, just it isnt considered a tag and thus not shown]
views.py
class EmployeeList(ListCreateAPIView): serializer_class = EmployeeDirectorySerializer def inner_company(self): company_hash = self.kwargs['company_hash'] return get_company(company_hash) def get_queryset(self): return Employee.objects.filter(company=self.inner_company())
test.py
class ApiTests(APITestCase): def setUp(self): self.factory = APIRequestFactory() self.staff = mommy.make('directory.Employee', user__is_staff=True) self.employee = mommy.make('directory.Employee') self.hash = self.employee.company.company_hash def getResponse(self, url, myView, kwargs): view = myView.as_view() request = self.factory.get(url, kwargs) force_authenticate(request, user=user) response = view(request) return response def test_EmployeeList(self): kwargs = {'timestamp': 0, 'company_hash': self.hash} url = reverse('employeelist', kwargs=kwargs) testedView = EmployeeList response = self.getResponse(url, testedView, kwargs=kwargs) self.assertEqual(response.status_code, 200)
I'm getting this error
company_hash = self.kwargs['company_hash'] KeyError: 'company_hash'
That is the args aren't been passed to the view.
I've tried in so many different ways to pass by the args, can't find a solution.
Any help is welcomed!
Upvotes: 7
Views: 3640
Reputation: 1865
You should pass kwargs
twice: into reverse(...)
and into view(...)
:
def test_EmployeeList(self):
# some init here
auth_user = ...
hash = ...
# form kwargs for url /<company_hash>/<timestamp>/employees/
kwargs = {'company_hash': hash, 'timestamp': 0}
# form url itself
url = reverse('employeelist', kwargs=kwargs)
# then form factory and request
factory = APIRequestFactory()
request = factory.get(url)
force_authenticate(request, user=auth_user)
# get view
view = EmployeeList.as_view()
# run view
# here you pass kwargs again!
response = view(request, **kwargs)
self.assertEqual(response.status_code, 200)
PS. Actually @bachir-mehemmel's answer lead me to that code but he is wrong telling kwargs
should be passed to get
(I think he means factory.get
). If you open factory.get
implementation you'll see that it is used for payload and not for url.
Upvotes: 0
Reputation: 159
you just need to specify your kwargs again when calling get()
method:
...
...
def getResponse(self, url, myView, kwargs):
view = myView.as_view()
request = self.factory.get(url, kwargs)
...
response = view(request, company_hash=kwargs['company_hash'])
return response
So your argument will be passed correctly.
NB: i used this solution based on my experience with the mother class of APIRequestfactory, Django RequestFactory.
Upvotes: 2
Reputation: 109
Just found the problem!!
I was using APIRequestFactory() and should have been using the build in client factory from the APITestCase test class from Django Rest Framework
Upvotes: -2
Reputation: 61
Check your regex syntax in your URL conf. You aren't capturing the named group correctly. You have
(?<P
rather than
(?P<
https://docs.djangoproject.com/en/1.8/topics/http/urls/#named-groups
-James
Upvotes: 5