Django如何模拟访问令牌

huangapple go评论53阅读模式
英文:

Django how to mock access token

问题

我在测试用例中有以下代码。每次运行测试用例时,都会生成一个新的令牌,这会消耗我的配额。

所以,我想使用一些模拟值来替代实际的令牌,需要通过APIClient成功进行身份验证。如何模拟这个令牌身份验证?
任何帮助都不胜感激。谢谢。

设置

'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTStatelessUserAuthentication',
],

测试用例

from apps.common.helpers import get_auth0_access_token

class TestDatasetListTestCase(APITestCase):
    def setUp(self):
        access_token = get_auth0_access_token()
        self.client.credentials(HTTP_AUTHORIZATION=f"Bearer {access_token}")

        payload = {"label": "new_label"}
        response = self.client.post(self.url, payload, format="multipart")

helpers.py

def generate_new_auth0_token()
    options = {
        "url": f"https://{auth0_domain}/oauth/token",
        "headers": {"cache-control": "no-cache", "content-type": "application/json"},
        "json": {"audience": audience, "grant_type": grant_type, "client_id": client_id, "client_secret": client_secret},
    }
    res = requests.post(**options)
    return res.json() or Exception(res.text)
英文:

I have the following code in my testcase. Whenever I'm running the testcase, a new token is generated which is draining my quota.

So,instead of actual token I want to use some mock value which needs to be authenticated by the APIClient successfully. How do I mock this token authentication ?
Any help is much appreciated. Thanks

Settings

'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTStatelessUserAuthentication',
],

Testcase

from apps.common.helpers import get_auth0_access_token

class TestDatasetListTestCase(APITestCase):
    def setUp(self):
        access_token = get_auth0_access_token()
        self.client.credentials(HTTP_AUTHORIZATION=f"Bearer {access_token}")

        payload = {"label": "new_label"}
        response = self.client.post(self.url, payload, format="multipart")

helpers.py

def generate_new_auth0_token()
    options = {
        "url": f"https://{auth0_domain}/oauth/token",
        "headers": {"cache-control": "no-cache", "content-type": "application/json"},
        "json": {"audience": audience, "grant_type": grant_type, "client_id": client_id, "client_secret": client_secret},
    }
    res = requests.post(**options)
    return res.json() or Exception(res.text)

答案1

得分: 0

在单元测试中,对于外部API的标准流程是将它们模拟。在测试期间调用这些API没有意义,因为它们预期会正常工作,除非对方发生了变化(比如更改API),但在您的情况下这是不被期望的,因为您正在使用标准API(通过oAuth固定规范),除非客户服务器宕机。

class TestDatasetListTestCase(APITestCase):
    @mock.patch('apps.common.helpers.get_auth0_access_token')
    def test_access_token(self, mock_access_token):
        mock_access_token.return_value = SomeFactory().get_test_access_token()
        access_token = get_auth0_access_token()
        self.client.credentials(HTTP_AUTHORIZATION=f"Bearer {access_token}")

        payload = {"label": "new_label"}
        response = self.client.post(self.url, payload, format="multipart")

如果您仍然想测试APIClient,我建议设置一个模拟的oAuth服务器,比如这个开源项目Mock oAuth Server。然后,您可以向API调用提供测试URL(或模拟它)。假设您的URL在设置中定义,可以尝试以下操作:

from django.test import override_settings

@override_settings(API_AUTH_URL='http://localhost:8989', CLIENT_SECRET='something', CLIENT_ID='else')
class TestDatasetListTestCase(APITestCase):

并更新辅助函数:

def generate_new_auth0_token()
    options = {
        "url": f"https://{settings.API_AUTH_URL}/oauth/token",
        "headers": {"cache-control": "no-cache", "content-type": "application/json"},
        "json": {"audience": audience, "grant_type": grant_type, "client_id": settings.CLIENT_ID, "client_secret": settings.CLIENT_SECRET},
    }

有关设置覆盖的更多信息,请参阅文档

英文:

In unit tests, the standard procedure for external APIs is to have them mocked. There is no point in calling these APIs during tests because these are expected to work unless something changes on the other side (like changing APIs), but it is not expected in your case because you are using a standard API (with a fixed set of specifications by oAuth), unless the client server is down.

class TestDatasetListTestCase(APITestCase):
   @mock.patch('apps.common.helpers.get_auth0_access_token')
   def test_access_token(self, mock_access_token):
        mock_access_token.return_value = SomeFactory().get_test_access_token()  # just using Factory pattern here, it can be hard coded string
        access_token = get_auth0_access_token()
        self.client.credentials(HTTP_AUTHORIZATION=f"Bearer {access_token}")

        payload = {"label": "new_label"}
        response = self.client.post(self.url, payload, format="multipart")

If you still willing to to test APIClient, then I suggest setting up a mock oAuth server, like this opensource project Mock oAuth Server. Then you can provide the test url the API calls (Or mock it). Lets say your url is defined in settings, you can try like this:

from django.test import override_settings

@override_settings(API_AUTH_URL='http://localhost:8989', CLIENT_SECRET='something', CLIENT_ID='else')
class TestDatasetListTestCase(APITestCase):

And update the helper function:

def generate_new_auth0_token()
    options = {
        "url": f"https://{settings.API_AUTH_URL}/oauth/token",
        "headers": {"cache-control": "no-cache", "content-type": "application/json"},
        "json": {"audience": audience, "grant_type": grant_type, "client_id": settings.CLIENT_ID, "client_secret": settings.CLIENT_SECRET},
    }

More information can be found in the documentation regarding settings override.

huangapple
  • 本文由 发表于 2023年5月6日 20:59:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/76189026.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定