Expected view to be called with a URL keyword argument named "pk"
Asked Answered
C

2

33

I'm writing a test for a Django Rest Framework view following closely the testing documentation

Here's my simple test:

def test_patient_detail_api_opens(self):
    factory = APIRequestFactory()
    view =PatientDetailApi.as_view()
    request = factory.get(reverse('api_pacjent', kwargs={'pk' :1}))
    force_authenticate(request, user=self.user)
    response = view(request)
    self.assertEqual(response.status_code, 200)

This test fails with the following message:

AssertionError: Expected view PatientDetailApi to be called with a URL keyword argument named "pk". Fix your URL conf, or set the `.lookup_field` attribute on the view correctly.

I fail to understand why this is happening and how to fix this.

  • The pk kwargs is there in the URL,
  • according to the docs there's no need to add the lookup-field value explicitly if it defaults to pk,
  • the view opens correctly and yet this test fails...

Can somebody please explain why this error occurs?

Here's the relevant code:

the 'main' url.py:

urlpatterns = [
    url(r'^pacjent/', include('pacjent.urls')),
] 

pacjent.urls looks like this:

url(r'^api/szczegoly/(?P<pk>\d+)/$', PatientDetailApi.as_view(), name="api_pacjent"),

And PatientDetailApi is this:

class PatientDetailApi(generics.RetrieveUpdateAPIView):
    model = Patient
    serializer_class = PatientDetailsSerializer
    queryset = Patient.objects.all()

    authentication_classes = (SessionAuthentication, BasicAuthentication)
    permission_classes = (IsAuthenticated,) 
Cogan answered 23/1, 2017 at 10:10 Comment(3)
Does it work when you actually request the api outside of your test, eg via Postman? Or if you use the APIClient?Messenia
It does. It was the missing part mentioned by RemcoGerlich. Thanks for your suggestion!Cogan
@Cogan what will be the API endpoint if you call your API from postman with named argument?Neanderthal
S
55

View functions are called with the request and the arguments from the URL. So pass them:

response = view(request, pk=1)
Schott answered 23/1, 2017 at 10:22 Comment(1)
OMG, I tried to add it to the as_view and then the factory.get, then trying to fiddle with the request itself...Sufferable
E
8

I encountered similar error when I made a mistake of using get_object method in perform_create. Read why this wrong from documentation

perform_create(self,instance):
      instance = self.get_object()
Elite answered 18/11, 2019 at 16:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.