我正在为基于 Django 类的 View 编写单元测试。
class ExampleView(ListView):
def get_context_data(self, **kwargs):
context = super(EampleView, self).get_context_data(**kwargs)
## do something else
def get_queryset(self, **kwargs):
return self.get_data()
def get_data(self):
call_external_API()
## do something else
关键问题是get_data()中的call_external_API()。
当我在写单元测试的时候,我真的不想调用外部API来获取数据。首先,那会花我的钱;其次,我可以轻松地在另一个测试文件中测试该 API。
我还可以轻松地测试此 get_data() 方法,方法是仅对其进行单元测试并模拟 call_external_API() 的输出。
但是,当我测试整个基于类的 View 时,我会这样做
self.client.get('/example/url/')
并检查状态码和上下文数据来验证它。
在这种情况下,当我测试整个基于类的 View 时,如何模拟此 call_external_API()?
请您参考如下方法:
您正在寻找的是 patch from unittest.mock .您可以修补 call_external_api()通过 MagicMock()目的。
也许你想打补丁 call_external_api()用于类里面的所有测试。 patch给你两种基本的方法
- 装饰测试类
- 使用
start()和stop()在setUp()和tearDown()分别
通过 patch 装饰一个类装饰器就像装饰所有的测试方法(详见文档),实现起来会很整洁。按照示例假设您的 View 在 my_view 中模块。
@patch("my_view.call_external_api", autospec=True)
class MyTest(unittest.TestCase):
def setUp(self):
self.client = Client()
def test_get_data(self, mock_call_external_api):
self.client.get('/example/url/')
self.assertTrue(mock_call_external_api.called)
可以构建更复杂的示例,您可以检查如何调用 mock_call_external_api并为您的 API 设置返回值或副作用。
我没有给出任何关于启动和停止方式的例子(我真的不喜欢它)但我想花一些时间在两个细节上:
- 我假设在你的
my_view您定义的模块call_external_api或者您通过from my_API_module import call_external_api导入它否则你应该注意Where to patch - 我用了
autospec=True: 恕我直言,它应该用于每个补丁调用和 documentation很好地解释为什么
