web-dev-qa-db-ja.com

認証にDjango-oauth-toolkitを使用してDjango-rest-frameworkでAPIエンドポイントをテストする方法

APIエンドポイントを定義するためのDjango-rest-frameworkビューセット/ルーターがあります。ビューセットは次のように定義されます。

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

そしてルーターは次のように定義されます

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

uRLパターン付きurl(r'^api/', include(router.urls))

適切なアクセストークンを取得して認証に使用することで、ブラウザでこのエンドポイントに到達できます。ただし、このエンドポイントに対してテストを作成する方法は明確ではありません。

これが私が試したことです:

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

これは、client.get()呼び出しからのHTTP401応答で失敗します。 oauth2認証にDjango-oauth-toolkitを使用してDRFでAPIエンドポイントをテストする正しい方法は何ですか?

17
Jim

テストを作成するときは、テスト自体からテストしていないものをすべて抽出することを目指す必要があります。通常は、テストのsetUpメソッドにセットアップコードを配置します。 OAuthを使用したAPIテストの場合、これには通常、テストユーザー、OAuthアプリケーション、およびアクティブなアクセストークンが含まれます。

Django-oauth-toolkitおよびその他のDjangoアプリケーションの場合、私は常に テストを見てどのように実行されるかを確認する をお勧めします。これにより、特にOAuthのようなマルチパートプロセスで不要なAPI呼び出しを行うことを回避し、必要ないくつかのモデルオブジェクトのみを作成できます。

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

そこから、生成されたトークンを使用して認証する必要があります。これを行うには、 Authorizationヘッダーを挿入 、または force_authenticateメソッドを使用 Django_が提供しますRESTフレームワーク。

25
Kevin Brown

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", "[email protected]", "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)

これで、すべてが期待どおりに機能します。お役に立てれば。ありがとう

0
Shinto Joseph