【问题标题】:How to mock Django Model Queries如何模拟 Django 模型查询
【发布时间】:2014-12-20 05:45:42
【问题描述】:

我想模拟以下CanonPerson 模型

def compute(self, is_send_emails, test_email_address):
        cpses = CanonPerson.objects.filter(persons__vpd=6,
                                           persons__country="United States",
                                           persons__role__icontains=';IX;').prefetch_related("persons").using("global")

        for cp in cpses:
           ...

我很迷茫如何模拟 CanonPerson.objects.filter 以返回一个可交互的集合,以便我可以继续。

这是我到目前为止所做的:

def test_X_count(self):
    with mock.patch('apps.dbank.models.CanonPerson.objects.filter') as canon_patch:
        mock_cp = mock.MagicMock(spec=CanonPerson)
        mock_person = mock.MagicMock(spec=Person)
        mock_person.vpd = 6
        mock_cp.country = "United States"
        mock_cp.role = ";IX;"
        mock_cp.persons.add(mock_person)
        canon_patch.objects.filter.return_value = [mock_cp] // ???
        oi = OptinInvites()
        oi.compute(False, None)
        oi.get_most_recent_email.assert_called_once_with(1)

在计算函数中,我可以看到 cpses 是一个 MagicMock 类型。 但是它是不可迭代的,之后的for loop 只是跳过它。 我想通过将返回值设置为[mock_cp] 我会创建一个可迭代列表?

【问题讨论】:

  • 尝试使用mock_django。也许对你有帮助。
  • 为什么不在测试中创建一些实际数据?这是做事的正常方式。或者使用factory boy之类的东西。
  • 想要模拟 django 模型的一个原因是,如果您想编写非常快速的单元测试。如果您想编写更完整的集成测试,那么不模拟模型非常好。这两种方法各有千秋。

标签: python django unit-testing python-mock


【解决方案1】:

您将返回值分配给canon_patch 的行略有错误。你在哪里:

canon_patch.objects.filter.return_value = [mock_cp]

应该是:

canon_patch.return_value = [mock_cp]

canon_patch 已经是“objects.filter”的模拟。

如果您调用CanonPerson.objects.filter.objects.filter(),您的原始行将返回[mock_cp]

如果您真的想修补 CanonPerson 模型,那么您的修补程序行将类似于:

with mock.patch('apps.dbank.models.CanonPerson') as canon_patch:

您可能还会发现您需要在它正在使用的位置模拟它,而不是您从中导入它的位置。因此,假设您在名为my_module 的模块中使用CanonPerson,您在测试中的补丁代码可能如下所示:

with mock.patch('my_module.CanonPerson') as canon_patch:

【讨论】:

  • 你说的很有道理。我已将其更改为 with mock.patch('apps.dbank.models.CanonPerson') as canon_patch:但是 cpses = CanonPerson.objects.filter( 指向真实模型而不是模拟对象。为什么补丁失败模拟整个模型应用程序?
  • 尝试在您使用它的模块中模拟它。而不是您从中导入它的模块。那有意义吗? your.module.CanonUser.
  • 我不确定,你的意思是我必须创建canon_patch 模拟并将其传递给oi.compute(False, None)?但这意味着我必须更改真实代码以适应要注入的模拟对象。我希望不必这样做。
  • 我在答案的末尾添加了一些内容,希望这应该更清楚一些。您无需修改​​实际代码。只是测试代码。
猜你喜欢
  • 1970-01-01
  • 2017-08-10
  • 2015-07-13
  • 1970-01-01
  • 1970-01-01
  • 2012-12-15
  • 2011-05-03
  • 1970-01-01
相关资源
最近更新 更多