【发布时间】:2018-03-10 13:39:54
【问题描述】:
我正在对一些 python3 代码进行单元测试,这些代码通过上下文管理器在 SMTP 类上调用 sendmail,并尝试捕获异常以记录它们。我可以成功地模拟 SMTP 类并在其他测试中对其进行一些检查(例如验证 send_message 是否被实际调用),但我似乎无法在要引发的类上调用 send_message 的方法记录错误的异常。
要测试的代码(来自 siteidentity_proxy_monitoring.py):
def send_alert(message, email_address):
with SMTP('localhost') as email:
try:
email.send_message(message)
except SMTPException:
# retry the send
print('exception raised') # debugging statement
try:
email.send_message(message)
except:
logging.error(
'Could not send email alert to %s', email_address
)
单元测试方法:
@unittest.mock.patch('siteidentity_proxy_monitoring.SMTP')
@unittest.mock.patch('siteidentity_proxy_monitoring.logging')
def test_logging_when_email_fails(self, mock_logger, mock_smtp):
"""
Test that when alert email fails to send, an error is logged
"""
test_print('Testing logging when email send fails')
email_instance = mock_smtp.return_value
email_instance.send_message.side_effect = SMTPException
siteidentity_proxy_monitoring.send_alert(
'test message',
'email@example.com'
)
mock_logger.error.assert_called_with(
'Could not send email alert to %s', 'email@example.com'
)
测试结果输出:
[TEST] ==> Testing logging when email send fails
F
======================================================================
FAIL: test_logging_when_email_fails (__main__.TestSiteidentityMonitors)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/lib/python3.6/unittest/mock.py",line 1179, in patched
return func(*args, **keywargs)
File "tests/siteidentity_monitor_tests.py", line 108, in
test_logging_when_email_fails
'Could not send email alert to %s', 'email@example.com'
File "/lib/python3.6/unittest/mock.py", line 805, in assert_called_with
raise AssertionError('Expected call: %s\nNot called' % (expected,))
AssertionError: Expected call: error('Could not send email alert to %s', 'email@example.com')
Not called
----------------------------------------------------------------------
Ran 4 tests in 0.955s
FAILED (failures=1)
我觉得我错过了与调用 __enter__ 和 __exit__ 相关的一些内容,但我似乎无法弄清楚为什么我的补丁似乎没有触发我期望的副作用到。不幸的是,我遇到的大多数示例和文档并没有深入到在上下文中模拟方法调用(无论如何,据我所知)。
【问题讨论】:
-
有一个正确模拟上下文管理器in the
unittest.mockdocs的例子。 -
感谢@jonrsharpe,但文档似乎指出了如何模拟实际的上下文管理器调用。我遇到的问题是我关心发生在上下文管理器内的方法调用。很可能是我对它们的了解有限,但我不知道如何降低范围以获取它们内部调用的方法。
-
那么你得到的实际输出是什么?
-
在原始问题中添加了测试输出。
标签: python python-3.x unit-testing mocking python-unittest