【问题标题】:Confirming function calls inside a function I'm unittesting with mock module在使用模拟模块进行单元测试时确认函数内部的函数调用
【发布时间】:2026-01-31 22:40:01
【问题描述】:

我有一个正在为其编写单元测试的函数。我试图断言在给定输入参数的情况下使用正确的参数调用了许多函数。例如,我正在单元测试的函数在一个名为 validate.py 的文件中

def function_to_test(arg1):
    print 'return2: ', _sub_function_1()
    arg1 = _sub_function_1(arg1)
    arg1 = _sub_function_2(arg1)
    arg1 = _sub_function_3(arg1)
    return arg1


def _sub_function_1(arg1):
    pass

def _sub_function_2(arg1):
    pass

def _sub_function_3(arg1):
    pass

我在一个名为 dotest.py 的文件中进行了单元测试,

import validate
import unittest
import mock

class TestFunctionToTest(unittest.TestCase):

    @mock.patch('validate._sub_function_1')
    def test_basic(self, m_sub_function_1):
        m_sub_function_1 = mock.Mock(return_value='rv_sf1')
        dum_arg1 = 'dum'
        out = validate.function_to_test(dum_arg1)
        print 'called?: ', m_sub_function_1.called

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

运行这个测试的结果是,

run -i dotest.py
return2:  <MagicMock name='_sub_function_1()' id='4502266128'>
called?:  False
.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK

由于某种原因,在对 _sub_function_1 的调用中无法识别为模拟函数定义的返回值。我想检查这个函数是否真的在function_to_test 中被调用。来自模拟大师的任何见解?

【问题讨论】:

    标签: python unit-testing mocking


    【解决方案1】:

    首先,您的test_basic 中似乎缺少self 参数。此外,您的代码不会调用function_to_test。就我个人而言,我将mock.patch 的参数写成一个字符串,所以它会变成:

    class TestFunctionToTest(unittest.TestCase):
    
        @mock.patch('validate._sub_function_1')
        def test_basic(self, m_sub_function_1):
            m_sub_function_1.return_value = 'rv_sf1'
            function_to_test(...)
    

    这应该打印:return2: rv_sf1。然后,您可以断言它已使用正确的参数调用:

    m_sub_function1.assert_called_with(...)
    

    【讨论】:

    • 谢谢。您发现的错误是由于我在将复杂的问题转换为更简单的测试用例时犯了错误。我仍然得到我的返回值在“return2”行中未被识别的结果。也许我在将问题转换为最小示例时遗漏了一些东西。让我编写代码,看看它是否有效。
    • 我已经确认我的最小示例仍然没有产生正确的返回值。我将编辑帖子以反映我正在使用的确切代码
    • @Gabriel:你试过上面的例子吗?您不应该替换单元测试中作为参数给出的模拟,您应该根据需要对其进行修改。否则你只是在修改一个局部变量。
    • 如果我将代码复制并粘贴到我的帖子中,我会得到我所显示的输出。你有什么不一样的吗?
    • @Gabriel:您帖子中的代码与上述答案的作用不同。