我正在尝试将Mock与Django用于两件事: 1.获取用户(我们有一个自定义后端,可以进行我想要的网络调用 避免) 2.模拟另一种方法,通过网络获取密码重置令牌。
以下是测试:
@patch('core.views.KagisoUser')
def test_forgot_password_sends_reset_email(self, MockKagisoUser): # noqa
email = 'mock@user.com'
user = MagicMock()
user.email = email
user.generate_reset_password_token.return_value = email
MockKagisoUser.objects.first.return_value = user
data = {'email': email}
client = Client()
response = client.post('/forgot_password/', data, follow=True)
message = list(response.context['messages'])[0].message
assert response.status_code == 200
assert 'You will receive an email with reset instructions shortly' \
== message
assert len(mail.outbox) == 1
assert mail.outbox[0].to[0] == email
assert mail.outbox[0].subject == 'Password Reset'
assert mail.outbox[0].alternatives[0] # HTML body
我收到此错误:
self = <django.core.mail.message.EmailMultiAlternatives object at 0x7f52eacd3390>
def message(self):
encoding = self.encoding or settings.DEFAULT_CHARSET
msg = SafeMIMEText(self.body, self.content_subtype, encoding)
msg = self._create_message(msg)
msg['Subject'] = self.subject
msg['From'] = self.extra_headers.get('From', self.from_email)
> msg['To'] = self.extra_headers.get('To', ', '.join(self.to))
E TypeError: sequence item 0: expected str instance, MagicMock found
以下是实施:
def forgot_password(request):
reset_message = 'You will receive an email with reset instructions shortly'
not_found_message = 'We could not find a user for that email address'
if request.method == 'POST':
form = forms.ForgotPasswordForm(request.POST)
if form.is_valid():
email = form.cleaned_data['email']
user = KagisoUser.objects.filter(email=email).first()
if user:
print(user.email)
token = user.generate_reset_password_token()
url = request.build_absolute_uri(reverse('reset_password'))
message = render_to_string(
'core/emails/reset_password.html',
{
'url': url,
'token': token,
'user_id': user.id
}
)
send_mail(
'Password Reset',
'',
'development@kagiso.io',
[user.email],
html_message=message
)
messages.success(request, reset_message)
return HttpResponseRedirect('/')
else:
messages.error(request, not_found_message)
return HttpResponseRedirect(reverse('forgot_password'))
else:
form = forms.ForgotPasswordForm()
return render(
request,
'core/auth/forgot_password.html',
{'form': form}
)
我做错了什么?
答案 0 :(得分:1)
堆栈跟踪非常有用......
但除此之外,您似乎嘲笑MockKagisoUser.objects.first
而您的视图从KagisoUser.objects.filter(email=email).first()
获取用户,因此您错过了filter
mock_filter = MagicMock()
mock_filter.first.return_value = user
MockKagisoUser.objects.filter.return_value = mock_filter
以上内容应该会返回一个过滤器,该过滤器会在获取first
时返回您的用户,而后者将在您的视图中返回您的用户,而不是返回MagicMock实例