【问题标题】:Django UnitTest with Mock带有 Mock 的 Django UnitTest
【发布时间】:2015-05-03 06:00:52
【问题描述】:

我正在为基于 Django 类的视图编写单元测试。

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

关键问题是call_external_API()get_data()

在编写单元测试时,我并不想调用外部 API 来获取数据。首先,这将花费我的钱;其次,我可以轻松地在另一个测试文件中测试该 API。

我还可以轻松地测试这个get_data() 方法,只对其进行单元测试并模拟call_external_API() 的输出。

但是,当我测试整个基于类的视图时,我会这样做

self.client.get('/example/url/')

并检查状态代码和上下文数据以验证它。

在这种情况下,我在测试整个基于类的视图时如何模拟这个call_external_API()

【问题讨论】:

  • 不确定您的两种情况有什么区别。为什么不能以同样的方式模拟它?

标签: python django unit-testing mocking


【解决方案1】:

您正在寻找的是patch from unittest.mock。您可以通过 MagicMock() 对象修补 call_external_api()

也许您想为课堂上的所有测试打补丁call_external_api()patch 基本上给你两种方法

  • 装饰测试类
  • 分别在setUp()tearDown()中使用start()stop()

patch装饰一个类就像装饰所有的测试方法(详见文档),实现会非常整洁。按照示例假设您的视图位于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 很好地解释了原因

【讨论】:

  • 这是我正在寻找的答案。谢谢!
【解决方案2】:

您可以在测试基于类的视图时模拟 call_external_api() 方法,如下所示:

import modulea
import unittest
from mock import Mock

class ExampleTestCase(unittest.TestCase):

     def setUp(self):
         self.call_external_api = modulea.call_external_api

     def tearDown(self):
         modulea.call_external_api = self.call_external_api

     def get_data(self):
         modulea.call_external_api = Mock(return_value="foobar")
         modulea.call_external_api()
         ## do something else

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-19
    • 2017-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多