Reputation: 21005
I have a Django-rest-framework API, that I want to unit test. More specifically, I want to unit test some data validation methods separately. These data validation methods will get a request as their parameter, like so:
def validate(request)
In order to test it separately, I need a way to create requests. In django-rest-framework, there is APIRequestFactory, that can be used in creating requests. The main problem is, that the APIRequestFactory will not create same request that the django-rest-framework uses. Instead, it will create regular django requests as stated by the site:
Note: When using APIRequestFactory, the object that is returned is Django's standard HttpRequest, and not REST framework's Request object, which is only generated once the view is called.
But because those validation methods use the django-rest-frameworks request, I cannot unit test those by using the APIRequestFactory. Is there any way to unit test separately those, or should I just use the APIClient, and try to test the whole APIView? I wouldn't want to do that, because then it will not be a pure unit test. And with the APIClient, I can only get responses, not requests. Why is there not an APIRequestFactory for the django-rest-framework requests? I mean, if those are the ones used in django-rest, then why the request factory doesn't generate those instead?
Upvotes: 7
Views: 2844
Reputation: 983
In my case it was sufficient (and quite straight forward) to just create a DRF Request
object using the django HttpRequest
that was returned by APIRequestFactory
. Though I agree with the sentiments of the OP in terms of wondering why APIRequestFactory
does not just do this in the first place. I ended up with something like the following:
from django.test import TestCase
from rest_framework.test import APIRequestFactory
from rest_framework.request import Request
class TestStuff(TestCase):
def setUp(self):
self.factory = APIRequestFactory()
def test_the_stuff(self):
req = Request(self.factory.get("/some/url"))
# req is now a DRF Request object, use accordingly...
Also if you are sending things that have a request body and want that to end up in request.data
it seems you need to explicitly specify the appropriate parser(s) like so:
from rest_framework.parsers import JSONParser
...
req = Request(
self.factory.post(
"/first?queryParamString=ok", {"random": "stuff"}, format="json"
),
parsers=[JSONParser()],
)
Upvotes: 1
Reputation: 21005
Was able bypass this by not sending the request to the validation method, but instead the request.DATA. This way the validation methods got independent on request, but only rely on the data sent to them.
Upvotes: 1