Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Rest Framework - AssertionError in tests

I have a problem with Django Rest Framework's tests. I have a following view:

class AccountDetail(generics.RetrieveUpdateAPIView):
    model = Account
    serializer_class = AccountSerializer
    lookup_field = 'username'
    permission_classes = (permissions.AllowAny,)
    def get_queryset(self):
        return Account.objects.filter(username=self.kwargs.get('username'))

My urls include the following:

account_urls = patterns('',
    url(r'^/(?P<username>[0-9a-zA-Z_-]+)/$', AccountDetail.as_view(), name='account-detail'),
    url(r'^/$', AccountList.as_view(), name='account-list')
)

urlpatterns = patterns('',
    url(r'^api/v1/users', include(account_urls)),
)

When I use the browsable API, everything works alright, but when I write the following test, I get an error:

class TestAccoundDetail(APITestCase):
    def setUp(self):
        factory = APIRequestFactory()
        #set up normal user and token
        self.normal_user = Account.objects.create_user(email="[email protected]", username="useri", password="man")
        request = factory.post('/api/v1/auth/login/', {'email': '[email protected]', 'password': 'man'})
        response = obtain_jwt_token(request)
        self.normal_token = response.data['token']

    def test_details(self):
        factory = APIRequestFactory()
        view = AccountDetail.as_view()

        #unauthenticated
        url = reverse('account-detail', kwargs={'username': 'useri'})
        request = factory.get(url)
        response = view(request)
        self.assertEqual(response.status_code, 200)

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

URL seems fine, and the lookup_field is there. What am I missing?

EDIT

I used APIClient instead and it works:

        client = APIClient()

        response = client.get('/api/v1/users/useri/')
        self.assertEqual(response.status_code, 200)

However, I still don't understand why my original test did not work.

like image 756
Jaakko Avatar asked Jul 11 '26 17:07

Jaakko


1 Answers

Expanding on @linovias answer, the key is to pass the extra arguments to your view

response = (view, username='useri')

Full test

def test_details(self):
    factory = APIRequestFactory()
    view = AccountDetail.as_view()

    #unauthenticated
    url = reverse('account-detail', kwargs={'username': 'useri'})
    request = factory.get(url)

    response = view(request, username='useri')

    self.assertEqual(response.status_code, 200)
like image 123
Henrik Andersson Avatar answered Jul 14 '26 07:07

Henrik Andersson