Python模拟补丁一个被另一个函数调用的函数

67
def f1():
    return 10, True

def f2():
    num, stat = f1()
    return 2*num, stat

如何使用Python的mock库来修补f1()并返回一个自定义结果,以便测试f2()

编辑: 我的测试有什么问题吗?这似乎不起作用,所有测试都失败了,并显示断言错误。

from foo.bar import f2
from mock import patch

class MyTest(TestCase):

    def test_f2_1(self):
        with patch('project.module.f1') as some_func:
            some_func.return_value = (20, False)
            num, stat = f2()
            self.assertEqual((num, stat), (40, False))

   @patch('project.module.f1')
   def test_f2_2(self, some_func):
       some_func.return_value = (20, False)
       num, stat = f2()
       self.assertEqual((num, stat), (40, False))
2个回答

58

第一个例子建议在同一模块中定义f1()和f2()。 因此,以下内容应该可以正常工作:

from foo.bar import f2
from unittest.mock import patch

class MyTest(TestCase):

    @patch('foo.bar.f1')
    def test_f2_2(self, some_func):
        some_func.return_value = (20, False)
        num, stat = f2()
        self.assertEqual((num, stat), (40, False))

补丁与导入相同:@patch('foo.bar.f1')

这里有一个关于这个问题的好答案:

http://bhfsteve.blogspot.nl/2012/06/patching-tip-using-mocks-in-python-unit.html


9
谢谢你推荐http://bhfsteve.blogspot.nl 关于修补程序和导入样式的链接,这解决了我的一个问题。 - HeyWatchThis
23
如果 f1f2 在不同的模块中,这会有什么不同? - Henry Woody

30

假设你正在使用这个mock库:

def f1():
    return 10, True

def f2():
    num, stat = f1()
    return 2*num, stat

import mock

print f2()   # Unchanged f1 -> prints (20, True)

with mock.patch('__main__.f1') as MockClass:       # replace f1 with MockClass 
    MockClass.return_value = (30, True)     # Change the return value

    print f2()     # f2 with changed f1 -> prints (60, True)
如果你的代码被分成模块,你可能需要用你模块/函数的路径来替换 __main__.f1

1
如果f1()接受参数,会有什么区别吗?例如:f1(arg)。 - Nam Ngo
2
Mocking函数可以使用任意数量的参数进行调用,它总是会返回return_value - Mariusz Jamro
非常感谢@Secator。我已经更新了我的问题,并提供了一个测试用例,但似乎没有通过。我做错了什么? - Nam Ngo
测试失败,抛出断言错误。 - Nam Ngo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接