Python 3.x 在类实例的方法内修补变量
我试图了解补丁是如何工作的,我正在使用pytest和Django视图进行测试: views.pyPython 3.x 在类实例的方法内修补变量,python-3.x,mocking,python-unittest,django-class-based-views,Python 3.x,Mocking,Python Unittest,Django Class Based Views,我试图了解补丁是如何工作的,我正在使用pytest和Django视图进行测试: views.py from django.contrib.auth.views import LoginView class MyLoginView(LoginView): pass test_view.py from django.test import RequestFactory from .views import MyLoginView rf = RequestFactory() def t
from django.contrib.auth.views import LoginView
class MyLoginView(LoginView):
pass
test_view.py
from django.test import RequestFactory
from .views import MyLoginView
rf = RequestFactory()
def test_login(rf):
request = rf.get(reverse('myapp:login'))
response = MyLoginView.as_view()(request)
assert response.status_code == 200
此操作失败,因为此视图调用数据库以使用以下函数获取当前站点:
失败:不允许访问数据库
如何模拟获取当前站点()
以避免数据库被命中
一个想法是使用pytest factoryboy的工厂
我设法模拟了LoginView。获取了上下文数据
,但我无法深入:
from django.test import RequestFactory
from .views import MyLoginView
from django.contrib.sites.models import Site
from pytest_factoryboy import register
from unittest.mock import patch
rf = RequestFactory()
class SiteFactory(factory.Factory):
class Meta:
model = Site
register(SiteFactory)
def test_login_social(rf, site_factory):
request = rf.get(reverse('myapp:login'))
with patch(
# 'django.contrib.auth.views.LoginView.get_context_data', # This is wrong
'django.contrib.auth.views.get_current_site', # Solution: Patch where it is imported, this works!
return_value=site_factory(name='example.com'),
):
response = CommunityLoginView.as_view()(request)
assert response.status_code == 200
编辑 解决方案是在以下范围内修补调用的方法:
带有补丁('django.contrib.auth.views.get\u current\u site')
由于
上下文数据是
你会怎么做?这里有两个选项:
pytest
仅允许,如果您显式标记测试函数,我们将访问数据库。如果没有这些信息,pytest
将在没有为测试构建数据库的情况下运行测试。我建议使用和提供的装饰
您已将添加到已安装的应用程序中。此应用程序是可选的,但如果您从单个Django应用程序提供多个不同页面,则此应用程序非常有用。曾经有一段时间,站点框架是强制性的,但由于它是可选的,我很少在我的安装的应用程序中包含它。也许你应该把它留给我
编辑:模拟
当然,模拟也应该工作,因为python中的每个对象都是可模拟的()。请记住,您必须修补模块/函数的位置,因为它绑定到本地作用域
要找到正确的位置,您可以搜索,查看如何使用以及如何正确修补,或者尝试进入PDB
。我不确定哪种方法有效,但我为您提供了两种选择:
pytest--pdb
python-mpdb-pytest
。这将立即打开调试器,您必须继续
一次pytest
现在将运行,直到出现第一个异常,PDB
将自动启动
现在可以使用bt
(回溯)、u
(向上走)、l
(显示源代码)和d
(向下走)查找数据库访问的位置
编辑2:工厂男孩
如果您使用的是factoryboy
,这取决于它是否尝试访问数据库。默认策略是.create()
,它会写入数据库
如果您使用site\u factory.build()
,它应该可以工作,因为这将无法访问您的数据库。谢谢!实际上,我并不打算测试Django。这只是一个很难理解的例子,patch
如何以及能做多远。@raratiru我更新了我的答案,以帮助找到模拟给定函数的正确方法。也许在获取当前站点()
旁边还有对数据库的多次访问。感谢您提供pdb技巧和链接。我成功地模拟了LoginView。获取了上下文数据,但我无法更深入地找到任何一个。。。现在我明白问题了!不知何故,我错过了您尝试使用factoryboy
创建Site
对象的机会。如果使用factoryboy
创建实例,这取决于它是否尝试访问数据库。默认策略是.create()
,它会写入数据库。如果您使用site\u factory.build()
,它应该可以工作,因为它不会访问您的数据库。谢谢,它不会访问数据库,因为我在不访问数据库的情况下修补了get\u context\u data
方法。实际上,我无法修补该方法中定义的变量class()
->def方法(self)
->variable=调用另一个模块()。