我在1.10 style中编写了自定义Django中间件,类似于:
class MyMiddleware(object):
def __init__(self, get_response):
self.get_response = get_response
# some initialization stuff here
def __call__(self, request):
# Code executed before view functions are called.
# Purpose of this middeware is to add new attribute to request
# In brief:
request.new_attribute = some_function_returning_some_object()
response = self.get_response(request)
# Code to be executed for each request/response after
# the view is called.
return response
请注意,这个中间件被威胁为一个单独的Python模块,不属于我项目中的任何特定应用程序,而是通过pip生活在外部并像其他任何软件包一样安装。它本身不起作用,但只有安装在Django应用程序中。
它工作正常,但是,我想测试一下。到目前为止我所做的是my_tests.py
:
from my_middleware_module import MyMiddleware
# some @patches
def test_mymiddleware():
request = Mock()
assert hasattr(request, 'new_attribute') is False # passes obviously
# CALL MIDDLEWARE ON REQUEST HERE
assert hasattr(request, 'new_attribute') is True # I want it to pass
我不知道如何调用request
变量上的中间件来修改它。我认为如果我使用类似函数的中间件风格会更容易,但如果我坚持使用我所拥有的东西并且我应该编写测试而不修改中间件会怎么样?
答案 0 :(得分:5)
问题是你没有调用MyMiddleware
的构造函数,也没有通过调用__call__
对象的实例来调用MyMiddleware
魔术方法。
有很多方法可以测试你描述的行为,我可以想到这个:
首先,我稍微修改了你自己的例子:
class MyMiddleware(object):
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
request.new_attribute = some_function_returning_some_object()
import ipdb; ipdb.set_trace()
response = self.get_response(request)
return response
def some_function_returning_some_object():
return 'whatever'
接下来,我通过实际创建Middleware对象并调用新创建的对象来创建测试,因为它是一个函数(因此运行__call__
)
from mock import patch, Mock
from middle import MyMiddleware
import unittest
class TestMiddleware(unittest.TestCase):
@patch('middle.MyMiddleware')
def test_init(self, my_middleware_mock):
my_middleware = MyMiddleware('response')
assert(my_middleware.get_response) == 'response'
def test_mymiddleware(self):
request = Mock()
my_middleware = MyMiddleware(Mock())
# CALL MIDDLEWARE ON REQUEST HERE
my_middleware(request)
assert request.new_attribute == 'whatever'
这里有一些有用的链接:
另一个SO问题中__call__和__init__之间的区别:__init__ or __call__?
从python文档中修补的位置:https://docs.python.org/3/library/unittest.mock.html#where-to-patch
pytest docs:http://docs.pytest.org/en/latest/contents.html
ipdb intro,对调试很有用:https://www.safaribooksonline.com/blog/2014/11/18/intro-python-debugger/
答案 1 :(得分:0)
好的,这有点晚了,但是我遇到了类似的问题,想为Google员工提供答案。
首先,我想出的一些答案建议在测试中创建一个brand
实例并设置一个_id
,但是this section显然会产生一个{{1}带有HttpRequest
的实例不能像HTTP服务器那样工作,并且继续:
它不支持中间件。如果需要视图本身正常运行,则测试本身必须提供会话和身份验证属性。
我已经想测试我的注射 是否在RequestFactory
对象中,因此我们必须创建一个。首先,我们创建一个虚拟视图:
HttpRequest
然后,我们需要将其链接到RequestFactory
中的URL。
HttpRequest
如果您已经使用pytest-django,则可以轻松获得具有def dummy_view(request, *args, **kwargs):
return HttpResponse(b"dummy")
固定装置的urls.py
实例,调用此URL并从响应中获取path("/dummy", dummy_view, name="dummy")
,如下所示:>
HttpClient
但这有一些缺点:
client
)包装URL。我发现这仅对第三方模块有用。