2014-12-24 10 views
14

Ich habe einen Viewset/Router mit Django-Rest-Framework, um einen API-Endpunkt zu definieren. Die Viewset wird als solche definiert:Testen eines API-Endpunkts mit Django-rest-framework mit Django-oauth-toolkit zur Authentifizierung

class DocumentViewSet(viewsets.ModelViewSet): 
    permission_classes = [permissions.IsAuthenticated, TokenHasReadWriteScope] 
    model = Document 

Und der Router als

router = DefaultRouter() 
router.register(r'documents', viewsets.DocumentViewSet) 

mit URL-Muster url(r'^api/', include(router.urls))

definiert ich diesen Endpunkt im Browser treffen kann/durch curl ganz gut, indem sie das richtige Zugriffstoken und es für die Autorisierung verwenden. Es ist jedoch nicht klar, wie Tests für diesen Endpunkt geschrieben werden.

Hier ist, was ich versucht habe:

class DocumentAPITests(APITestCase): 
    def test_get_all_documents(self): 
     user = User.objects.create_user('test', '[email protected]', 'test') 
     client = APIClient() 
     client.credentials(username="test", password="test") 
     response = client.get("/api/documents/") 
     self.assertEqual(response.status_code, 200) 

Dies scheitert mit einer HTTP-401-Antwort vom client.get() Anruf. Was ist der richtige Weg, um einen API-Endpunkt in DRF mit django-oauth-toolkit für die oauth2-Authentifizierung zu testen?

Antwort

23

Wenn Sie Tests schreiben, sollten Sie versuchen, alles, was Sie nicht testen, aus dem Test selbst zu extrahieren, indem Sie in der Regel den Setup-Code in die setUp Methode des Tests eingeben. Im Falle von API-Tests mit OAuth umfasst dies normalerweise den Testbenutzer, die OAuth-Anwendung und das aktive Zugriffstoken.

Für django-oauth-toolkit und andere Django-Anwendungen würde ich immer looking at the tests to see how they do it empfehlen. Auf diese Weise können Sie unnötige API-Aufrufe vermeiden, insbesondere bei mehrteiligen Prozessen wie OAuth, und nur die wenigen erforderlichen Modellobjekte erstellen.

def setUp(self): 
    self.test_user = UserModel.objects.create_user("test_user", "[email protected]", "123456") 

    self.application = Application(
     name="Test Application", 
     redirect_uris="http://localhost", 
     user=self.test_user, 
     client_type=Application.CLIENT_CONFIDENTIAL, 
     authorization_grant_type=Application.GRANT_AUTHORIZATION_CODE, 
    ) 
    self.application.save() 

def test_revoke_access_token(self): 
    from datetime import datetime 
    from django.utils import timezone 

    tok = AccessToken.objects.create(
     user=self.test_user, token='1234567890', 
     application=self.application, scope='read write', 
     expires=timezone.now() + datetime.timedelta(days=1) 
    ) 

Von dort müssen Sie nur mit dem Token authentifizieren, das generiert wurde. Sie können dies tun, indem Sie injecting the Authorization header, oder Sie können use the force_authenticate method von Django REST Framework zur Verfügung gestellt.

+1

Das ist das Ticket. Ich habe die Erstellung des Zugriffstokens vermisst + es war nicht klar, wie das Token in die Anfrage zu injizieren ist. Vielen Dank! – Jim

+0

Das war genau das, wonach ich suchte. Vielen Dank! – DanXPrado

Verwandte Themen