类的Mock属性

时间:2015-09-14 13:32:42

标签: 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.logger.info("Hello")

我想模仿self.logger.info不被调用。我试图使用patch('A.logging.info'),但它没有用。我也试过了patch('A.logging.getLogger'),但如果我在print type(self.logger)测试时我function(),我会得到一个记录对象而不是模拟对象。

2 个答案:

答案 0 :(得分:0)

创建实例时,您的属性设置为。只需修补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')

使用模拟,使用logging.getLogger()返回一个新的模拟对象(mock_log.return_value object),然后任何访问self.logger.info的尝试都返回mock_log.return_value.info对象,使用Mock.assert_called_with() method记录可测试的测试。

演示:

>>> import mock
>>> import logging
>>> class A(object): 
...     def __init__(self):
...         self.logger = logging.getLogger()
... 
>>> class B(A):
...     def function(self):
...         self.logger.info("Hello")
... 
>>> 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_logger
<MagicMock name='getLogger()' id='4375059984'>
>>> mock_logger.info
<MagicMock name='getLogger().info' id='4374917008'>
>>> mock_logger.info.call_args
call('Hello')

答案 1 :(得分:0)

真正的问题是您要修补 info记录器而非记录器。要做到这一点,你应该使用

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()返回一个全局对象,所以即使在补丁上下文之前创建了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')]