如何模拟Django模型对象(及其方法)?

时间:2017-08-04 17:47:06

标签: python django python-3.x unit-testing python-3.5

我正在尝试使用以下虚拟方法模拟链式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,这是在一篇文章中提到的。正确模拟模型对象(使用链式方法)的指针/提示很受欢迎。

提前谢谢你。

1 个答案:

答案 0 :(得分:10)

不要修补模型本身,而是修改模型。对象然后模拟链的每个部分:

@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()和其他模型操作。我还发现Model Mommy在测试Django模型时非常有用。