在Python中使用Mock()

11 投票
2 回答
4938 浏览
提问于 2025-04-17 03:06

你能给我一些关于在Django单元测试中使用Mock()的清晰例子吗?我想更清楚地理解它。

更新:我已经弄明白了一些事情,所以我在下面分享一下。

2 个回答

1

这个Mock网站有很不错的API文档,详细介绍了这些内容。需要注意的是,patch会替换掉所有地方调用的foo.Foo.foo。虽然这不是模拟东西的最佳方法,但有时候可能是唯一的办法——可以参考open()。

21

第一部分:基础知识

from mock import Mock

模拟对象(Mock object)是一种特殊的对象,它就像是我们不想执行的代码的一个“替身”。但是我们希望从这个“替身”那里获取一些信息,比如被调用的次数和调用时传入的参数。此外,我们还可以为这些代码指定一个返回值。

让我们定义一个简单的函数:

def foo(value):
    return value + value

现在我们准备为这个函数创建一个模拟对象:

mock_foo = Mock(foo, return_value='mock return value')

接下来我们可以检查一下:

>>> foo(1)
2
>>> mock_foo(1)
'mock return value'

并获取一些关于调用的信息:

>>> mock_foo.called
True
>>> mock_foo.call_count
1
>>> mock_foo.call_args
((1,), {})

Mock() 实例可用的属性有:

call_args       func_code       func_name
call_args_list  func_defaults   method_calls
call_count      func_dict       side_effect
called          func_doc        
func_closure    func_globals    

这些属性的意思都很明显。

第二部分:@patch 装饰器

@patch 装饰器让我们可以轻松地为导入的对象(类或方法)创建模拟对象。这在编写单元测试时非常有用。

假设我们有一个名为 foo.py 的模块:

class Foo(object):
    def foo(value):
        return value + value

现在我们来为 @patch 装饰器写一个测试。 我们将要对模块 foo 中的 Foo 类的 foo 方法进行补丁。别忘了导入相关内容。

from mock import patch
import foo

@patch('foo.Foo.foo')
def test(mock_foo):
    # We assign return value to the mock object
    mock_foo.return_value = 'mock return value'
    f = foo.Foo()
    return f.foo(1)

现在运行它:

>>> test()
'mock return value'

太好了!我们的方法成功被覆盖了。

撰写回答