如何在Python API测试中模拟

问题描述 投票:0回答:1

我正在尝试模拟下面的示例函数。不知怎的,我遇到了错误。 例如, 我有一堂课如下

myclass.py
:

import os, requests

class MyClass:
    def __init__(self, login_url):
        self.username = os.environ.get('username')
        self.password = os.environ.get('password')
        self.login_url = login_url
        self.auth_credentials = {
            'name': self.username,
            'password': self.password
        }

    def get_access_token(self):
        token = ""
        headers = {
            'Authorization': f'Bearer {token}',
            'Content-Type': 'application/json',
            'Accept': 'application/json'
        }
        response = requests.post(self.login_url, json=self.auth_credentials, headers=headers, verify=False)
        access_token = response.json().get('access_token')
        return access_token

现在,我正在进行如下单元测试

unit_test.py
,这实际上抛出了一个错误:

import os
import requests
import unittest
from unittest.mock import Mock, patch, MagicMock
import MyClass

class TestModule(unittest.TestCase):
    # @patch('MyClass.get_access_token')
    def test_execute(self):
        # Test/Mock API:
        _obj = MyClass(login_url="https://www.my-website.com/login/")

        mock_access_token = "abc123def456ghi789"
        with patch('MyClass.get_access_token') as _access:
            _access.return_value.status_code = 200
            _access.return_value.json.return_value = mock_access_token
            response = _obj.get_access_token()
            self.assertEqual(response.status_code, 200)
            self.assertEqual(response, mock_access_token)


if __name__ == "__main__":
    unittest.main()

那么,我在

unit_test.py
中错过了什么?

python unit-testing mocking python-unittest python-unittest.mock
1个回答
0
投票

在这一行中,您将

MyClass.get_access_token
替换为
MagicMock
实例:

with patch('MyClass.get_access_token') as _access:

这意味着每次您调用某些方法时,它将开始返回另一个

MagicMock
。它还会忽略
get_access_token
方法中的所有内容(你用模拟替换了它,还记得吗?)。但是,您的测试代码仍在尝试测试此方法的内部逻辑,例如访问响应的方法。

这里你真正想要模拟的是网络请求,而不是你的方法。您的方法本身没有任何副作用,它调用的库却有。所以你需要模拟库,在这种情况下

requests
。您需要实现适当的模拟,以便当
get_access_token
调用
requests.post
时,它不会实际发出 POST 请求,而是返回具有适当成员的模拟响应(如
json()
)。

由于

requests
有点复杂,您可能会发现这很有帮助:如何模拟请求和响应?

© www.soinside.com 2019 - 2024. All rights reserved.