Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

django test RequestFactory cannot get route parameter to work

Tags:

python

django

I have a problem that I don't know how to make it work.

urls.py:

urlpatterns = [
    url(r'athletes/search$', SearchAthletes.as_view()),
    url(r'athletes/([0-9]+)$', ViewAthlete.as_view())
]

views.py:

class ViewAthlete(APIView):

    def get(self, request, id, format=None):
        athlete = Athlete.objects.get(id=id)
        serializer = AthleteSerializer(athlete)
        return Response(serializer.data)

test.py:

def test_view_athlete(self):
    tmp = Athlete.objects.order_by('?')[0]

    request = self.factory.get('/_api/v1/athletes/' + str(tmp.id))
    request.user = AnonymousUser()

    response = ViewAthlete.as_view()(request)
    self.assertEquals(response.data.id, tmp.id)

I keep getting the following error:

Traceback (most recent call last): File "/tests.py", line 44, in test_view_athlete response = ViewAthlete.as_view()(request)

File "/venv/lib/python3.5/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view return view_func(*args, **kwargs)

File "/venv/lib/python3.5/site-packages/django/views/generic/base.py", line 68, in view return self.dispatch(request, *args, **kwargs)

File "/venv/lib/python3.5/site-packages/rest_framework/views.py", line 474, in dispatch response = self.handle_exception(exc)

File "/venv/lib/python3.5/site-packages/rest_framework/views.py", line 471, in dispatch response = handler(request, *args, **kwargs) TypeError: get() missing 1 required positional argument: 'id'

To my understanding, the problem is that, there is no id parameter passed to get function of ViewAthelete view class. What is the reason for this? In development environment (not testing), it displays the data but testing environment doesn't recognize the arguments from the route.

like image 902
Gasim Avatar asked Dec 24 '22 02:12

Gasim


2 Answers

AFAIK urlpatterns are considered when testing through the full django request stack, e.g.: through django.test.Client, using it's get/post methods

When testing your view directly (MyView.as_view()(request)) the whole url resolver logic is bypassed, and then the args/kwargs need to be supplied by the caller (e.g.: MyView.as_view()(request, 'arg1', 'arg2', id='34'))

like image 109
zsepi Avatar answered Dec 26 '22 15:12

zsepi


As zsepi says, your URLs aren't used here. To avoid repeating the arguments, rather than calling the view directly you could use the test client to "call" the URL: another advantage of doing this is that the middleware runs, so you don't need to assign the user attribute separately.

response = self.client.get('/_api/v1/athletes/' + str(tmp.id)) 
like image 43
Daniel Roseman Avatar answered Dec 26 '22 15:12

Daniel Roseman