Lets say I have this APIView
class Dummy(APIView):
def get(self, request):
return Response(data=request.query_params.get('uuid'))
To test it, I need to create a request object to pass into the get
function
def test_dummy(self):
from rest_framework.test import APIRequestFactory
factory = APIRequestFactory()
request = factory.get('/?uuid=abcd')
DummyView().get(request)
It complains about AttributeError: 'WSGIRequest' object has no attribute 'query_params'
Having a closer look, the factory creates a WSGIRequest
instance instead of a DRF version <class 'rest_framework.request.Request'>
.
>>> from rest_framework.test import APIRequestFactory
>>> factory = APIRequestFactory()
>>> request = factory.get('/')
>>> request.__class__
<class 'django.core.handlers.wsgi.WSGIRequest'>
Refer to Tom's solution,
DummyView()(request)
will raise error:Instead, should use
as_view
just like what you do inurls.py
:DRF's
as_view
uses methodinitialize_request
to convert Django Request object to DRF version. You can try with:You can also use APIClient to run test. It also tests URL dispatching.
I realize this answer is some time after the question was asked, but it solved this issue for me. Just override the
APIRequestFactory
class as below.That's right. At the moment
APIRequestFactory
returns anHttpRequest
object, which only get upgraded to a REST frameworkRequest
object once it gets to the view layer.This mirrors the behavior that you'll see in an actual request, and what it does do is deal with eg. rendering JSON, XML or whatever other content type you have configured for your test requests.
However I agree that it's surprising behavior and at some point it will probably return a
Request
object, and the REST framework view will ensure that it only performs theRequest
upgrade on requests that instances ofHttpRequest
.What you need to do in your case is actually call the view, rather than invoking the
.get()
method...