Python 类的Mock属性

Python 类的Mock属性,python,unit-testing,mocking,Python,Unit Testing,Mocking,我正在对一个文件进行单元测试,在模拟类B中的属性或函数调用(self.logger.info)时遇到问题。我有两个类a和B,B继承自a import logging class A(object): def __init__(self): self.logger = logging.getLogger() 在另一个模块中: from A import A class B(A): def function(self): self.logg

我正在对一个文件进行单元测试,在模拟类B中的属性或函数调用(
self.logger.info
)时遇到问题。我有两个类a和B,B继承自a

import logging

class A(object): 
    def __init__(self):
        self.logger = logging.getLogger()
在另一个模块中:

from A import A

class B(A):  
    def function(self):
        self.logger.info("Hello")
我想模拟不被调用的
self.logger.info
。我试着使用
补丁('A.logging.info')
,但没有成功。我也尝试了
patch('A.logging.getLogger')
,但是如果我在
function()
print type(self.logger)
进行测试,我会得到一个日志对象,而不是模拟对象。

在创建实例时设置属性。只需修补
logging.getLogger
甚至
logging.Logger.info

如果您修补
logging.getLogger()
调用,您也不必修补任何其他
self.logger
调用,因为生成的模拟将处理其上的任何属性:

with mock.patch('logging.getLogger') as mock_log:
    mock_logger = mock_log.return_value
    b = B()
    b.function()
    mock_logger.info.assert_called_with('Hello')
在mock就位后,使用
logging.getLogger()
返回一个新的mock对象(the),任何试图访问
self.logger.info
的操作都会返回
mock\u log.return\u value.info
对象,该对象将使用

演示:

导入模拟 >>>导入日志记录 >>>A类(对象): ... 定义初始化(自): ... self.logger=logging.getLogger() ... >>>B(A)类: ... def功能(自我): ... self.logger.info(“你好”) ... >>>使用mock.patch('logging.getLogger')作为模拟日志: ... mock\u logger=mock\u log.return\u值 ... b=b() ... b、 函数() ... mock_logger.info.assert_使用('Hello')调用_ ... >>>模拟记录器 >>>mock_logger.info >>>mock_logger.info.call_args 打电话('你好')
真正的问题是,您只想修补记录器,而不想修补记录器。要做到这一点,你应该使用

patch.object(logging.getlogger(), 'info')

>>> from mock import patch
>>> with patch.object(logging.getLogger(), "info") as mock_info:
...     B().function()
...     print(mock_info.mock_calls)
...     mock_info.assert_called_with("Hello")
[call('Hello')]
有趣的是,
logging.getLogger()
返回一个全局对象a,因此即使在补丁上下文之前创建了
B
对象,该方法也可以工作:

>>> b = B()
>>> with patch.object(logging.getLogger(), "info") as mock_info:
...     b.function()
...     print(mock_info.mock_calls)
...     mock_info.assert_called_with("Hello")
... 
[call('Hello')]

我已经尝试只修补logging.getLogger,但它不起作用。如果我做了一个补丁(a.logging.getLogger)和一个打印类型(self.logger),我仍然会得到一个日志对象,而不是模拟对象。A类和B类在不同的文件中。@RomanzoCriminale:那么在你的问题中显示出来。包括它是如何对你不起作用的(比如,告诉我们实际发生了什么以及你期望发生什么)。@RomanzoCriminale:注意,我告诉过你修补
logging.getLogger
,而不是
A.logging.getLogger
@RomanzoCriminale:no,
mock.patch()
负责为您处理该问题。我正在尝试更新我的示例,因为即使有您的帮助,我也无法使其工作。我删除了
B.\uuu init\uuu()
方法,因为a)它本身没有做任何事情,是冗余的,B)您的
super()
调用无效(使用
super(B,self)
,而不是
super(a,self)
)。对于错误,我尝试做一个快速的示例来表示我的实际代码。在生成新示例时要小心,因为它仍然会重现您遇到的问题。首先测试您发布的代码,以确保您没有意外删除问题的根源。哦,它确实有效。也可以在帮助中心中看到。好的,问题是我在所有单元测试中创建了一个要测试的对象,当我在创建对象后添加日志补丁时,它无法工作。
>>> b = B()
>>> with patch.object(logging.getLogger(), "info") as mock_info:
...     b.function()
...     print(mock_info.mock_calls)
...     mock_info.assert_called_with("Hello")
... 
[call('Hello')]