如何模拟一个Django模型对象(及其方法)?
问题描述:
我试图嘲弄链式Django的模型对象在以下假设法,如何模拟一个Django模型对象(及其方法)?
# utils.py
def foo_something_exist():
if Foo.objects.get(a='something').exist():
return 'exist'
# test.py
import unittest.mock import patch
import utils
.
.
.
@patch('utils.Foo')
def test_foo_something_exist_returns_none(self, mock_foo):
mock_foo.objects.get.exists.return_value = False
self.assertIsNone(utils.foo_something_exist())
.
.
.
test_foo_something_exist()
未能通过测试。我发现utils.py中的Foo.objects.get(a='something').exist()
是MagicMock对象(<MagicMock name='Member.objects.get().exists()' id='xxxxxx'>
)而不是False
,这导致了此测试功能的失败。是的,我也试过mock_foo.objects.return_value.get.return_value.exists.return_value = False
,这是在一篇文章中提到的。正确地模拟模型对象(使用链式方法)的指针/提示值得欣赏。
预先感谢您。
答
不修补模型本身,而是model.objects然后嘲笑链的每一个部分:
@patch('utils.Foo.objects')
def test_foo_something_exist_returns_none(self, mock_foo):
# just to show how to do it with longer chains
# mock_foo.filter.return_value = mock_foo
# mock_foo.exclude.return_value = mock_foo
mock_foo.get.return_value = mock_foo
mock_foo.exists.return_value = False
self.assertIsNone(utils.foo_something_exist())
这也工作与.filter()
,.exclude()
和其他模型操作。在测试Django模型时,我也发现Model Mommy真的很有用。
谢谢你的回答。我可以知道'mock_foo.get.return_value = mock_foo'是做什么的吗? – tebesfinwo
它使用修补后的对象作为每个链接方法调用的返回值。所以你最终得到一个有方法的补丁对象,并且它们都返回相同的补丁对象。这种方式也无关紧要你链接方法调用的顺序。 – masterfloda