我想在pytest中测试以下功能,而不需要实际创建SMTP服务器并将电子邮件发送到指定地址。
def send_email_investor_owner_occupier(self,user_type,smtp_server):
message=MIMEMultipart()
message['From']=self.email_address
message['To']=self.email_address
suburb_set={suburb for location in user_type.locations for suburb in location.keys()}
suburb_string=','.join(suburb_set)
message['Subject']=f'Investment Properties in {suburb_string} last updated {user_type.date_posted}'
body= f'{user_type.properties} with {user_type.bedrooms} bedrooms, {user_type.bathrooms} bathrooms,{user_type.car_spaces} car spaces, priced between ${user_type.min_price} and ${user_type.max_price} in {suburb_string} last updated {user_type.date_posted}. Key metrics calculated for {user_type.loan_type} {user_type.variable_loan_type if user_type.variable_loan_type!=None else ""} loan with {user_type.lvr/100} lvr for {user_type.loan_term} years with {user_type.mortgage_interest}% interest.'
message.attach(MIMEText(body,"plain"))
message.attach('property_data.csv',self.property_data_io.getvalue(),'text/csv')
with smtplib.SMTP(smtp_server,self.port) as server:
server.starttls()
server.login(self.email_address,self.password)
server.sendmail(self.email_address,self.email_address,message.as_string())
server.quit()
我知道SMTP服务器可以根据https://jingwen-z.github.io/how-to-send-emails-with-python/但我无法用pytest计算出来。如果可能的话,我希望能够在pytest中做到这一点,因为我的所有其他测试都使用该模块。
我不完全确定您在寻找什么,因为您的函数不会返回任何内容。但我想您可以断言哪些函数在send_email_investor_owner_occupier
中被调用。
要在pytest中使用mocker,我所做的就是安装pytest mock模块。然后,您可以将测试定义为:
def test_something(mocker):
mocker.patch(foo.bar, return_value=True)
assert foo.bar()
如果你知道如何在unittest中进行mock,那么在pytest中进行嘲讽就很容易了。
假设包含send_email_investor_owner_occupier
方法的python模块称为my_email_sender.py
,然后对my_email_sender.smtplib.SMTP
进行修补。
一种方法是使用补丁装饰器:
from unittest.mock import patch
@patch("my_email_sender.smtplib.SMTP")
def test_send_email_investor_owner_occupier_patch_decorator(smtp_mock):
# call send_email_investor_owner_occupier
# assert like: smtp_mock.assert_called_once_with("server", port)
pass
另一种方法是使用pytest模拟插件进行pytest:
pip install pytest-mock
def test_send_email_investor_owner_occupier_pytest_mock_plugin(mocker):
smtp_mock = mocker.MagicMock(name='smtp_mock')
mocker.patch('my_email_sender.smtplib.SMTP', new=smtp_mock)
# call send_email_investor_owner_occupier
# assert like: smtp_mock.assert_called_once_with("server", port)
pass
这可能看起来有点乏味,但如果你有几个测试来检查邮件发送,并且你想在不复制相同代码的情况下轻松地模拟所有这些测试,你可以将这种方法与pytest fixture混合使用:
import pytest
@pytest.fixture
def smtp_mock(mocker):
smtp_mock = mocker.MagicMock(name='smtp_mock')
mocker.patch('my_email_sender.smtplib.SMTP', new=smtp_mock)
yield smtp_mock
def test_send_email_investor_owner_occupier_pytest_fixture(smtp_mock):
# call send_email_investor_owner_occupier
# assert like: smtp_mock.assert_called_once_with("server", port)
pass
def test_send_email_investor_owner_occupier_pytest_fixture_2(smtp_mock):
# call send_email_investor_owner_occupier
# assert like: smtp_mock.assert_called_once_with("server", port)
pass
def test_send_email_investor_owner_occupier_pytest_fixture_3(smtp_mock):
# call send_email_investor_owner_occupier
# assert like: smtp_mock.assert_called_once_with("server", port)
pass