Cómo probar un punto final de API con Django-rest-framework utilizando Django-oauth-toolkit para la autenticación

Tengo un conjunto de vistas / enrutador Django-rest-framework para definir un punto final de API. El conjunto de vistas se define como tal:

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

Y el enrutador se define como

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

con url patrón url(r'^api/', include(router.urls))

Puedo acceder a este punto final en el navegador / a través de la curvatura simplemente obteniendo el token de acceso correcto y usándolo para la autorización. Sin embargo, no está claro cómo escribir pruebas en este punto final.

Esto es lo que he intentado:

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

Esto falla con una respuesta HTTP 401 de la llamada client.get() . ¿Cuál es la forma correcta de probar un punto final de API en DRF utilizando django-oauth-toolkit para la autenticación auth2?

Cuando está escribiendo pruebas, debe aspirar a extraer cualquier cosa que no esté probando de la prueba, por lo general, debe colocar cualquier código de configuración en el método de setUp de la prueba. En el caso de las pruebas de API con OAuth, esto generalmente incluye el usuario de prueba, la aplicación OAuth y el token de acceso activo.

Para django-oauth-toolkit , y otras aplicaciones de Django, siempre recomendaría mirar las pruebas para ver cómo lo hacen . Esto le permite evitar hacer llamadas de API innecesarias, especialmente para procesos de varias partes como OAuth, y solo crear los pocos objetos modelo que se requieren.

 def setUp(self): self.test_user = UserModel.objects.create_user("test_user", "test@user.com", "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) ) 

Desde allí, solo necesita autenticarse utilizando el token que se ha generado. Puede hacer esto inyectando el encabezado de Authorization , o puede usar el método force_authenticate proporcionado por Django REST Framework.

He usado la misma biblioteca para OAuth2,

Esto funciono para mi

 from oauth2_provider.settings import oauth2_settings from oauth2_provider.models import get_access_token_model, get_application_model from django.contrib.auth import get_user_model from django.utils import timezone from rest_framework.test import APITestCase Application = get_application_model() AccessToken = get_access_token_model() UserModel = get_user_model() class Test_mytest(APITestCase): def setUp(self): oauth2_settings._SCOPES = ["read", "write", "scope1", "scope2", "resource1"] self.test_user = UserModel.objects.create_user("test_user", "test@example.com", "123456") self.application = Application.objects.create( name="Test Application", redirect_uris="http://localhost http://example.com http://example.org", user=self.test_user, client_type=Application.CLIENT_CONFIDENTIAL, authorization_grant_type=Application.GRANT_AUTHORIZATION_CODE, ) self.access_token = AccessToken.objects.create( user=self.test_user, scope="read write", expires=timezone.now() + timezone.timedelta(seconds=300), token="secret-access-token-key", application=self.application ) # read or write as per your choice self.access_token.scope = "read" self.access_token.save() # correct token and correct scope self.auth = "Bearer {0}".format(self.access_token.token) def test_success_response(self): url = reverse('my_url',) # Obtaining the POST response for the input data response = self.client.get(url, HTTP_AUTHORIZATION=self.auth) # checking wether the response is success self.assertEqual(response.status_code, status.HTTP_200_OK) 

Ahora todo funcionará como se espera. Espero que esto ayude. Gracias