如何模拟一个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真的很有用。

+0

谢谢你的回答。我可以知道'mock_foo.get.return_value = mock_foo'是做什么的吗? – tebesfinwo

+0

它使用修补后的对象作为每个链接方法调用的返回值。所以你最终得到一个有方法的补丁对象,并且它们都返回相同的补丁对象。这种方式也无关紧要你链接方法调用的顺序。 – masterfloda