Python中的单元测试/模拟

时间:2017-07-11 20:45:33

标签: python unit-testing dependency-injection mocking

所以我想说我有这段代码:

import coolObject

def doSomething():
   x = coolObject()
   x.coolOperation()

现在这是一个非常简单的方法,正如您所看到的,我们正在使用外部库(coolObject)。 在单元测试中,我必须创建一个大致复制它的对象的模拟。我们称这个模拟对象为coolMock

我的问题是如何告知代码何时使用coolMockcoolObject?我在网上查了一下,有些人建议依赖注入,但我不确定我是否正确理解。

提前致谢!

2 个答案:

答案 0 :(得分:1)

def doSomething(cool_object=None):
  cool_object = cool_object or coolObject()
  ...

在你的测试中:

def test_do_something(self):
   cool_mock = mock.create_autospec(coolObject, ...)
   cool_mock.coolOperation.side_effect = ...
   doSomthing(cool_object=cool_mock)
   ...
   self.assertEqual(cool_mock.coolOperation.call_count, ...)

答案 1 :(得分:1)

正如Dan的回答所说,一个选项是使用依赖注入:让函数接受一个可选参数,如果它没有传递使用默认类,那么测试可以传入一个MOC。

另一个选择是使用mock库(herehere)来替换coolObject

我们假设你有foo.py看起来像

from somewhere.else import coolObject

def doSomething():
    x = coolObject()
    x.coolOperation()

test_foo.py你可以做到:

import mock

def test_thing():
    path = 'foo.coolObject'  # The fully-qualified path to the module, class, function, whatever you want to mock.
    with mock.patch('foo.coolObject') as m:
       doSomething()
       # Whatever you want to assert here.
       assert m.called

您使用的path可以包含对象的属性,例如module1.module2.MyClass.my_class_method。一个很大的问题是你需要模拟被测模块中的对象,而不是它被定义的位置。在上面的示例中,这意味着使用foo.coolObject而不是somwhere.else.coolObject的路径。