我编写了一个自定义类来模拟代码库中的通用 API 客户端,这样我就可以集中轻松地模拟所有类方法以进行单元测试。到目前为止,这工作得很好,但是我正在寻找一种方法来跟踪对每个类方法的单独调用。现在,唯一可通过 Mock 进行跟踪的调用是初始类实例化。
这是模拟课:
from faker import Factory
faker = Factory.create()
class MockAPIClass
def get_some_data(self, data):
return f"{data} - {faker.pyint()}"
然后在我的util文件中:
def func_to_test_that_calls_client(arg):
client = regular_api_client()
return client.get_some_data(arg)
然后在我的单元测试中:
from unittest import mock
from django.test import TransactionTestCase
from .file import MockAPIClass
from .util import func_to_test_that_calls_client
class TestUils(TransactionTestCase):
def setUp(self):
self.api_call_patcher = mock.patch('path.to.mocked.class.instantiation')
self.patch_api = self.api_call_patcher.start()
self.mock_api = MockAPIClass() # this done so that the mocked class can be referenced below
self.patch_api.return_value = self.mock_api
def tearDown(self):
mock.patch.stopall()
def test_util_func(self):
res = func_to_test_that_calls_client("test")
self.assertTrue(res)
self.patch_api.assert_called_once()
以上功能完全符合预期和预期。但是,在函数
func_to_test_that_calls_client
中,原始客户端被实例化,然后类方法 get_some_data()
被调用。通过此实现,我看不到类方法的调用堆栈,例如该函数,只能看到该类的父实例化。例如,我希望能够看到 func_to_test_that_calls_client
在当前的实现中被 "test"
调用。有没有办法用模拟或其他一些 python 技巧来做到这一点?
一个标准的
Mock
对象(这是patch
默认使用的对象)工作正常。无需构建您自己的特殊模拟课程。
使用它作为你的
util.py
的模拟版本(我需要添加一个虚拟的regular_api_client
来为patch
设定目标):
regular_api_client = lambda: None
def func_to_test_that_calls_client(arg):
client = regular_api_client()
return client.get_some_data(arg)
这个简单的测试似乎可以满足您的需求:
from unittest.mock import patch
from util import func_to_test_that_calls_client
def test_util_func():
with patch('util.regular_api_client') as mock_client_class:
mock_client = mock_client_class()
func_to_test_that_calls_client("test")
mock_client.get_some_data.assert_called_with("test")
请注意,您可以通过将
assert_called_with("test")
更改为 assert_called_with("something else")
并查看现在测试失败了:
E AssertionError: expected call not found.
E Expected: get_some_data('something else')
E Actual: get_some_data('test')