【问题标题】:How to test an API endpoint with Django-rest-framework using Django-oauth-toolkit for authentication如何使用 Django-oauth-toolkit 使用 Django-rest-framework 测试 API 端点以进行身份​​验证
【发布时间】:2015-02-22 20:31:33
【问题描述】:

我有一个 Django-rest-framework 视图集/路由器来定义 API 端点。视图集是这样定义的:

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

而路由器定义为

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

带有网址格式url(r'^api/', include(router.urls))

通过获取正确的访问令牌并将其用于授权,我可以在浏览器中/通过 curl 访问此端点。但是,尚不清楚如何针对此端点编写测试。

这是我尝试过的:

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) 

这将失败,来自client.get() 调用的 HTTP 401 响应。使用 django-oauth-toolkit 进行 oauth2 身份验证在 DRF 中测试 API 端点的正确方法是什么?

【问题讨论】:

    标签: python django testing oauth-2.0 django-rest-framework


    【解决方案1】:

    我为 OAuth2 使用了相同的库,

    这对我有用

    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)
    

    现在一切都会按预期进行。 希望这可以帮助。谢谢

    【讨论】:

      【解决方案2】:

      当您编写测试时,您的目标应该是从测试本身中提取您未测试的任何内容,通常将任何设置代码放入测试的 setUp 方法中。在使用 OAuth 进行 API 测试的情况下,这通常包括测试用户、OAuth 应用程序和活动访问令牌。

      对于django-oauth-toolkit 和其他 Django 应用程序,我总是推荐looking at the tests to see how they do it。这使您可以避免进行不必要的 API 调用,尤其是对于像 OAuth 这样的多部分流程,并且只创建少数需要的模型对象。

      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)
          )
      

      从那里您只需要使用已生成的令牌进行身份验证。你可以通过injecting the Authorization header 来实现,也可以通过Django REST Framework 提供的use the force_authenticate method 来实现。

      【讨论】:

      • 这就是票。我错过了访问令牌的创建+不清楚如何将令牌注入请求中。谢谢!
      • 这正是我想要的。非常感谢!
      猜你喜欢
      • 2015-08-30
      • 2018-07-04
      • 2017-08-15
      • 2015-06-01
      • 2017-04-13
      • 2016-08-06
      • 2015-09-16
      • 2018-05-19
      • 2019-05-18
      相关资源
      最近更新 更多