使用MagicMock模拟smtplib.SMTP的send_message时断言调用失败
断言失败的原因及解决办法
核心问题
你把send_message的mock配置在了SMTP类对象上,但业务代码里实际调用的是SMTP实例对象的send_message方法,两者不是同一个对象,自然断言失败。
具体来说:
- 测试代码里的
mock_client是smtplib.SMTP这个类的mock,你配置的mock_client.send_message是类方法的mock - 业务代码中
with smtplib.SMTP("localhost") as server创建了SMTP的实例server,实际调用的是server.send_message(msg)——也就是实例方法,和类的mock没关系
修正后的测试代码
你需要针对SMTP类实例的mock来配置send_message,也就是通过mock_client.return_value(它对应类实例化后的对象)来设置:
import email_sender as es from unittest.mock import patch import smtplib def test_send_message_input_success() -> None: with patch("smtplib.SMTP", spec=smtplib.SMTP) as mock_client: # 获取SMTP实例的mock对象(对应业务代码里的server) mock_server = mock_client.return_value # 配置实例的send_message方法 mock_server.send_message.return_value = None es.sendMessage() # 断言SMTP类被实例化过 assert mock_client.called == True # 断言实例的send_message被调用 assert mock_server.send_message.called == True
或者也可以用configure_mock直接配置实例方法:
mock_client.configure_mock( **{ "return_value.send_message.return_value": None } ) # 断言时改为检查实例方法的调用状态 assert mock_client.return_value.send_message.called == True
补充说明
mock_client作为类的mock,它的called属性为True,是因为业务代码里调用了smtplib.SMTP("localhost")——也就是实例化了这个类,所以类的mock被调用了,但类本身的send_message方法根本没被触发过,这就是第二个断言失败的原因。
内容的提问来源于stack exchange,提问作者N0000B
相关产品推荐
相关产品推荐

