我在Flask应用程序中构建了一个用户邀请系统,并希望使用Python unittest进行测试。我正在使用SendGrid发送电子邮件。如何在测试期间阻止SendGrid实际发送电子邮件?我可以收到用户邀请链接并将其拉入我的测试中吗?我的代码如下:
# views.py
@app.route('/add_user', methods=['GET', 'POST'])
@login_required
@groups_required(['site_admin'])
def add_user():
"""
Send invite email with token to invited user
"""
form = AddUserForm()
if form.validate_on_submit():
# token serializer
ts = URLSafeTimedSerializer(app.config['SECRET_KEY'])
email = request.form['email']
tenant_id = user.custom_data['tenant_id']
# create token containing email and tenant_id
token = ts.dumps([email, tenant_id])
# create url with token, e.g. /add_user_confirm/asdf-asd-fasdf
confirm_url = url_for(
'add_user_confirm',
token=token,
_external=True)
try:
# sendgrid setup
sg = sendgrid.SendGridClient(
app.config['SENDGRID_API_KEY'],
raise_errors=True
)
# email setup
message = sendgrid.Mail(
to=request.form['email'],
subject='Account Invitation',
html='You have been invited to set up an account on PhotogApp. Click here: ' + confirm_url,
from_email='support@photogapp.com'
)
# send email
status, msg = sg.send(message)
flash('Invite sent successfully.')
return render_template('dashboard/add_user_complete.html')
# catch and display SendGrid errors
except SendGridClientError as err:
flash(err.message.get('message'))
except SendGridServerError as err:
flash(err.message.get('message'))
return render_template('dashboard/add_user.html', form=form)
@app.route('/add_user_confirm/<token>', methods=['GET', 'POST'])
def add_user_confirm(token):
"""
Decode invite token and create new user account
"""
form = RegistrationForm()
decoded = None
try:
ts = URLSafeTimedSerializer(app.config['SECRET_KEY'])
decoded = ts.loads(token, max_age=86400)
email = decoded[0]
except:
abort(404)
if form.validate_on_submit():
try:
tenant_id = decoded[1]
data = {}
data['email'] = email
data['password'] = request.form['password']
# given_name and surname are required fields
data['given_name'] = 'Anonymous'
data['surname'] = 'Anonymous'
# set tenant id and site_admin status
data['custom_data'] = {
'tenant_id': tenant_id,
'site_admin': 'False'
}
# create account
account = User.create(**data)
# add user to tenant group
account.add_group(tenant_id)
# login user
login_user(account, remember=True)
# success redirect
return render_template('account/add_user_complete.html')
except StormpathError as err:
flash(err.message.get('message'))
elif request.method == 'POST':
flash("Passwords don't match.")
return render_template('account/add_user_setpassword.html',
form=form,
email=email)
# tests.py
def test_add_user(self):
resp = self.client.post('/add_user', data={
'email': self.test_email
}, follow_redirects=True)
assert 'User invitation sent' in resp.data
答案 0 :(得分:1)
所以这是一个非常完美的模拟案例。模拟背后的基本思想是你用普通的传递,失败,副作用替换当前的功能(在这种情况下,发送电子邮件)。
If you're using Python 2.7 you'll have to download the mock third party package
否则你可以说
from unittest import mock
In this particular case I'd suggest using mock.patch
# tests.py
from unittest import mock
@mock.patch("sg.send")
def test_add_user(self, mocked_send):
mocked_send.return_value = None # Do nothing on send
resp = self.client.post('/add_user', data={
'email': self.test_email
}, follow_redirects=True)
assert 'User invitation sent' in resp.data
这将使得当sg.send
被调用时,它将调用模拟函数而不是实函数。由于默认情况下模拟是空白的,因此不会发送可怕的电子邮件。
注意:SendGrid
需要在test.py
文件中导入并在范围内。