如何模拟不在测试范围内的方法?

时间:2014-06-14 15:39:27

标签: python python-2.7 mocking

如何模拟不在测试范围内的方法?

或:如何模拟未直接调用的方法?

在这种情况下方法 baz
我正在使用pypi的Mock package

### tests
# ...
def test_method_a(self):
    # how to mock method that is called from bar() ?
    obj = foo.bar()
    self.assertEqual(obj.get('x'), 12345)

### foo
# ...
def bar():
    x = some_module.baz()  # <- how to mock baz() ?
    return x

2 个答案:

答案 0 :(得分:3)

以下示例应该向您展示它的工作原理:

from mock import patch

def baz():
  return 'y'


def bar():
  x = baz()  # <- how to mock baz() ?
  return x


def test():
  with patch('__main__.baz') as baz_mock:
    baz_mock.return_value = 'blah'
    assert bar() == 'blah'
test()

答案 1 :(得分:0)

恕我直言这个例子更好地说明了单元测试中的常见用例。

重要的部分是@patch装饰器,它有效地替换了正在修补的函数的side_effect函数(这也可能只是一个值)。棘手的位通常是获得修补功能的完整包路径。请注意您必须使用'__main__.func'来引用修补函数。

第一个测试test_func检查测试的模拟值是原始预期函数值('Hello World!')。第二个测试test_mocked_func补丁func实际上是函数对象new_func,因此返回True。第三个测试说明将值替换为side_effect而不是新函数。事实上,由于我们使替换值成为可迭代的(side_effect=['New String 1!', 'New String 2!', 3]),因此每次运行时,它都会返回一个新值。

警告:如果您尝试调用修补函数的时间超过指定的返回值(本例中为3),则会出现StopIteration错误,因为您没有定义足够的返回side_effect中的值。

import unittest
from mock import patch # for Python 2.7
# from unittest.mock import patch # for Python 3.5

def func():
    return 'Hello World!'

def newFunc():
    return True

class TestFunc(unittest.TestCase):

    def test_func(self):
        self.assertEqual(func(), 'Hello World!')

    @patch('__main__.func', side_effect=newFunc)
    def test_mocked_func(self, *patches):
        self.assertTrue(func())

    @patch('__main__.func', side_effect=['New String 1!', 'New String 2!', 3])
    def test_mocked_func_again(self, *patches):
        self.assertEqual(func(), 'New String 1!')
        self.assertEqual(func(), 'New String 2!')
        self.assertEqual(func(), 3)
        # func() # This breaks the test because we only specified a list of length 3 in our patch.

if __name__=='__main__':
    unittest.main()