我怎样才能正确模拟这个 python 函数?

How can I mock out this python function properly?

我在名为 my_file.py 的文件中有以下函数:

import logging
log = logging.getLogger(__name__)

class MyClass:
    def my_func(self):
        print("Entered my_func()")
        print("log.error = {}".format(log.error))
        log.error("Hello World")

my_func() 为 运行 时,我看到此输出:

Entered my_func()
log.error =  <bound method ProcessAwareLogger.error of <celery.utils.log.ProcessAwareLogger object at 0x7fd52d4f0d50>> 

我想编写一个单元测试用例来检查每当调用 my_func() 时,都会使用参数 "Hello World".

调用 log.error()

所以我的测试用例是这样的:

import mock
from my_file import MyClass

@mock.patch("my_file.logging.error")
def test_parse_response_with_error(self, mock_log_error):
    m = MyClass()
    m.my_func()
    mock_log_error.assert_called_once_with("Hello World")

当我 运行 这个测试用例时,我得到错误: AssertionError: Expected to be called once. Called 0 times. 所以我的补丁显然不起作用。我指定的路径 my_file.logging.error 错了吗?我怎样才能使它正常工作以便单元测试用例通过?

你嘲笑错了。 log.error 创建了一个不同于 logging.error 的绑定方法,并且该方法已经引用了在创建补丁之前保存的“真实”logging.error

相反,直接模拟 Logger 实例的 error 属性。

@mock.patch.object(my_file.log, 'error'):
def test_it(self, mock_log_error):
    m = MyClass()
    m.my_func()
    mock_log_error.assert_called_once_with("Hello World")

(在 导入 my_file 之前修补 logging.error 可能会起作用。)