django - 如果在 Django 表单保存方法中调用了一个函数,如何使用 pytest 检查?
问题描述
是)我有的
在表单的 save 方法中调用了两个函数:generate_random_password
和send_email
,我需要知道是否调用了这些函数,因为generate_random_password
它会为每个新创建的用户随机分配一个密码,并向用户send_email
发送一封电子邮件通知,其中包含凭据、生成的密码和用户登录。重要的是要知道这些函数是否在 save 中正确执行。
class UserAdminCreationForm(forms.ModelForm):
class Meta:
model = User
fields = ()
def save(self, commit: bool = True) -> U:
user = super(UserAdminCreationForm, self).save(commit=False)
data = self.cleaned_data
# Set random password for every new user
random_password = generate_random_password()
user.set_password(random_password)
# Send email confirmation with credentials to login
email = data.get("email")
html_message = render_to_string(
template_name="mails/user_creation_notification.html",
context={"email": email, "password": random_password},
)
# Strip the html tag. So people can see the pure text at least.
plain_message = strip_tags(html_message)
send_mail(
subject="Bienvenido a TodoTránsito",
message=plain_message,
recipient_list=[email],
html_message=html_message,
)
# Save into the DB the new user
if commit:
user.save()
return user
问题
我pytest
用来测试我的 Django 代码,但我不知道如何断言这些函数是否被调用。
解决方案
根据您在评论中写的内容,我猜想模拟这两个函数可能是有意义的,因为您可能并不真的需要在测试中使用随机密码。您可以执行以下操作:
from unittest import mock
@mock.patch('some_module.generate_random_password', return_value='swordfish')
@mock.patch('some_module.send_mail')
def test_save_user(mocked_send_mail, mocked_generate_password):
user_form = create_user_form() # whatever you do to create the form in the test
user_from.save()
mocked_generate_password.assert_called_once()
mocked_send_mail.assert_called_once()
# or mocked_send_mail.assert_called_once_with(...) if you want to check the parameters it was called with
请注意,您必须确保模拟正确的模块,例如在测试代码中使用的模块(请参阅修补位置)。
在这种情况下generate_random_password
,被替换为总是返回相同密码send_mail
的模拟,并被替换为除了记录调用之外什么都不做的模拟。两个模拟都可以通过测试中的参数访问,这些参数由patch
装饰器注入(最后一个装饰器在前,参数名称是任意的)。
如果您安装pytest-mock
,您将获得mocker
夹具,它为您提供相同的功能以及更多功能。相同的代码会是这样的:
def test_save_user(mocker):
mocked_generate_password = mocker.patch('some_module.generate_random_password', return_value='swordfish')
mocked_send_mail = mocker.patch('some_module.send_mail')
user_form = create_user_form() # whatever you do to create the form in the test
user_from.save()
mocked_generate_password.assert_called_once()
mocked_send_mail.assert_called_once()
如果您现在想使用 real generate_random_password
,但仍想查看它是否被调用,则可以mocker.spy
改用:
def test_save_user(mocker):
mocked_generate_password = mocker.spy(some_module, 'generate_random_password')
mocked_send_mail = mocker.patch('some_module.send_mail')
user_form = create_user_form() # whatever you do to create the form in the test
user_from.save()
mocked_generate_password.assert_called_once()
mocked_send_mail.assert_called_once()
请注意unittest.mock.patch.object
,在我看来,您可以使用 实现相同的功能,但不太方便。
推荐阅读
- data-visualization - AttributeError:“列表”对象没有属性“rgb2hex”
- jmeter - Jmeter中的IE记录问题
- java - 我正在构建一个 Wallpaper Changer Java 应用程序,但遇到 BATCH 刷新桌面壁纸的问题
- netlogo - NetLogo 3.1.5 版中的错误:没有定义任何名为 PICKUP-NEAREST-CIRCLE
- uwp - 如何在 UWP TextBox 中停止字符替换(如 ... 到省略号)
- javascript - RegEx 至少有 3 个字符,第一个和最后一个字符也应该是单引号
- sql-server - 动态存储过程未更新 SQL Server 表
- php - Laravel:在 href 中传递 {id}
- string - 从 UART 字符构建字符串 - 家庭学习 C
- node.js - MongoDB & Node.js - 如何用 $eq 和 $cond 对字段求和,其中表达式是对象数组