Skip to main content
 首页 » 编程设计

python之带模拟的 Django 单元测试

2024年08月26日30三少

我正在为基于 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 设置返回值或副作用。

我没有给出任何关于启动和停止方式的例子(我真的不喜欢它)但我想花一些时间在两个细节上:

  1. 我假设在你的my_view您定义的模块 call_external_api或者您通过 from my_API_module import call_external_api 导入它否则你应该注意Where to patch
  2. 我用了autospec=True : 恕我直言,它应该用于每个补丁调用和 documentation很好地解释为什么