簡體   English   中英

在測試 Django REST 框架時,為什么我不能讓 APIClient.credentials() 使用令牌進行身份驗證?

[英]When testing Django REST Framework, why can't I get APIClient.credentials() to authenticate using a token?

我正在針對基本的 API 編寫功能(不是單元)測試,如下所示:

from decouple import config
from rest_framework.test import APIClient, APITestCase


class ObjectAPIResponseTest(APITestCase):
    base_url = 'http://localhost:8000/api/objects/'
    token = config('LOCAL_API_TOKEN') # token stored in local .env file
    authenticated_client = APIClient()

    def setUp(self):
        self.authenticated_client.credentials(HTTP_AUTHORIZATION='Token ' + self.token)

    def test_list_object_reaches_api(self):
        real_response = self.authenticated_client.get(self.base_url)

        self.assertEqual(real_response.status_code, 200)
        self.assertEqual(real_response.headers['content-type'], 'application/json')

測試失敗: AssertionError: 401 != 200

After successfully testing the request with curl, I decided to try to load up requests with the Authorization header instead of using Django REST Framework's APIClient :

import requests

from decouple import config
from rest_framework.test import APIClient, APITestCase


class ObjectAPIResponseTest(APITestCase):
    base_url = 'http://localhost:8000/api/objects/'
    token = config('LOCAL_API_TOKEN') # token stored in local .env file

    authentication_header = {
        'Authorization': 'Token ' + token
    }

    def test_list_object_reaches_api(self):
        real_response = requests.get(self.base_url, headers=self.authentication_header)

        self.assertEqual(real_response.status_code, 200)
        self.assertEqual(real_response.headers['content-type'], 'application/json')

這通過了,這讓我想知道我是否以某種方式錯誤地使用APIClient.credentials() ,盡管我所做的似乎基本上與文檔一致。

任何想法我做錯了什么?

更新

受 Hafnernuss 評論的啟發,我想看看APIClient請求的行為如何,因此我檢查了APIClient請求和requests請求的響應。

看起來APIClient實際上並沒有命中在我的開發服務器上運行的 API 端點,盡管我明確要求它的 URL。 如果我刪除需要對請求進行身份驗證的權限並通過 APIClient 發送請求:

client_response = self.authenticated_client.get(self.base_url)
print(client_response.data)

我得到這個response.data

[]

不過,我知道我的本地數據庫中至少有一個 object 可以通過該端點訪問。 如果我在測試的上下文中創建一個新的 object 並運行請求,我會得到 object 返回:

[OrderedDict([('id', 3), ('property', 'foo')])]

所以我認為我對APIClient的幕后情況有一個根本的誤解。 是否以某種方式 mocking 向我的本地開發服務器的 URL 發出請求並從從測試運行者的數據庫中提取的人為端點請求?

這是繞過 API 身份驗證的替代解決方案:

事實上,為了禁用任何類型的 API 身份驗證(令牌、基本等),您只需在test_method()之上使用以下裝飾器:

from unittest.mock import patch

from <Respetive-App>.<Respective-Views> import <Respective-View>

@patch.object(<Respective-View>, "permission_classes", [])
def test_post_rate(self, api_client):
    payload = dict(content_id=self.content.id, score=5)
    response = api_client.post(
        "/api/endpoint/",
        payload,
    )
    assert response.status_code == 201

將用戶的主鍵添加到此

base_url = 'http://localhost:8000/api/objects/' + f'{user.pk}/'

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM