pytest - 如何修补方法以避免数据库调用
pytest - How to patch a method to avoid database call
出于学习的目的,我正在尝试编写一个测试来修补 Django 的 authenticate
函数,以避免必须访问数据库。我编写的代码不起作用,我不明白为什么。我在网上搜索过,但发现很多我读到的内容令人困惑。任何帮助将不胜感激。
我正在使用 Django、DRF、pytest、pytest-django 和 pytest-mock。
from django.contrib.auth import authenticate
from rest_framework.test import APIRequestFactory
def test_authenticate(mocker, user_factory):
user = user_factory.build()
mocker.patch('django.contrib.auth.authenticate', return_value=user)
factory = APIRequestFactory()
request = factory.get('/')
data = {
'username': user.email,
'password': 'testpassword',
}
assert user == authenticate(request=request, **data)
在上面的代码中,user_factory
来自 conftest.py
,我们可以假设它按预期工作。
我收到的错误是:
E Failed: Database access not allowed, use the "django_db" mark, or the "db" or "transactional_db" fixtures to enable it.
同样,我想避免必须将测试标记为数据库访问。相反,我希望能够模拟 authenticate
并控制它的 return 值。
打补丁的规则 #1:您对应该打补丁的第一个猜测总是错误的。
修补规则 #2:不要修补 IS 的地方,而是修补 WILL 在执行期间查找的地方。
您导入了 authenticate
并将其作为 authenticate
添加到命名空间。
修补程序时,将 django.contrib.auth.authenticate
导入到命名空间,然后模拟它。
稍后您调用 authenticate
,您在开始时导入的原始版本 - 而不是修补程序为您导入的模拟版本。
通过仅导入 django.contrib.auth
然后修补 django.contrib.auth.authenticate
,修补程序 'sneaks' 在其模拟 authenticate
中进入 django.contrib.auth
。
如果您随后使用 user == django.contrib.auth.authenticate
进行断言,python 将在 django.contrib.auth
中查找 authenticate
并将找到模拟。
经典补丁之谜:
https://docs.python.org/3/library/unittest.mock.html#where-to-patch
出于学习的目的,我正在尝试编写一个测试来修补 Django 的 authenticate
函数,以避免必须访问数据库。我编写的代码不起作用,我不明白为什么。我在网上搜索过,但发现很多我读到的内容令人困惑。任何帮助将不胜感激。
我正在使用 Django、DRF、pytest、pytest-django 和 pytest-mock。
from django.contrib.auth import authenticate
from rest_framework.test import APIRequestFactory
def test_authenticate(mocker, user_factory):
user = user_factory.build()
mocker.patch('django.contrib.auth.authenticate', return_value=user)
factory = APIRequestFactory()
request = factory.get('/')
data = {
'username': user.email,
'password': 'testpassword',
}
assert user == authenticate(request=request, **data)
在上面的代码中,user_factory
来自 conftest.py
,我们可以假设它按预期工作。
我收到的错误是:
E Failed: Database access not allowed, use the "django_db" mark, or the "db" or "transactional_db" fixtures to enable it.
同样,我想避免必须将测试标记为数据库访问。相反,我希望能够模拟 authenticate
并控制它的 return 值。
打补丁的规则 #1:您对应该打补丁的第一个猜测总是错误的。
修补规则 #2:不要修补 IS 的地方,而是修补 WILL 在执行期间查找的地方。
您导入了 authenticate
并将其作为 authenticate
添加到命名空间。
修补程序时,将 django.contrib.auth.authenticate
导入到命名空间,然后模拟它。
稍后您调用 authenticate
,您在开始时导入的原始版本 - 而不是修补程序为您导入的模拟版本。
通过仅导入 django.contrib.auth
然后修补 django.contrib.auth.authenticate
,修补程序 'sneaks' 在其模拟 authenticate
中进入 django.contrib.auth
。
如果您随后使用 user == django.contrib.auth.authenticate
进行断言,python 将在 django.contrib.auth
中查找 authenticate
并将找到模拟。
经典补丁之谜: https://docs.python.org/3/library/unittest.mock.html#where-to-patch