Reputation: 2109
I already read: Django REST Framework - Set request in serializer test?. And it doesn't work for me! Because I'm using APIClient and not RequestFactory like him.
I built a web app where the back-end is implemented using the Django REST Framework. Now I'm writing unit tests and I have come across a problem in testing my serializer methods. Here is one example of a serializer method I'm struggling with:
def get_can_edit(self, obj):
request = self.context['request']
user = User.objects.get(username=request.user)
return user == obj.admin
When trying to call this from the test, first I declare an instance of the serializer:
But now I need self.serializer to have the correct request when get_can_edit does self.context.get('request'). I've created a fake request with the correct information using APIClient:
self.client = APIClient()
self.client.force_authenticate(user)
conference = a_fake_conference
res = self.client.get('conference:conference-detail'. args=[conference.id])
serializer = ConferenceSerializer(conference, context={WHAT_IS_REQUEST?})
# I'm using a dict as context but the request gave me an error: context={'request': { 'user': user }}
sert.assertEqual(res.data, serializer.data)
Now I am stuck because I am unsure how to add request1 to serializer such that request = self.context['request']
will return
Thanks.
Upvotes: 2
Views: 1690
Reputation: 6408
You're testing two things with each other here, so that's sort of part of the problem. Typically, you'd use self.client.get(...)
as an integration test, that is, a test that ensures that everything from request to response is working as expected. For tests like these, you wouldn't use a serialiser, because then you're using your application code (your serialiser) to test itself.
If you're writing an integration test, you should be testing the raw response with something like:
from django.test import TestCase, RequestFactory
class MyUnitTestCase(TestCase):
def test_the_whole_stack(self):
response = self.client.get(
"conference:conference-detail", args=[conference.id]
)
self.assertEqual(response.status_code, 200)
self.assertEqual(
response.json()["some-key-you-expect"],
"Some value you expect"
)
Note that you also don't have to invoke APIClient()
directly. It's there by default.
For a unit test, like the kind of test you'd write to make sure your serialiser is working properly, you don't need or want to be poking around with a WSGIRequest object. Instead, Django supplies a RequestFactory for just this case:
from django.test import TestCase, RequestFactory
class MyUnitTestCase(TestCase):
def test_my_serialiser(self):
serializer = ConferenceSerializer(
conference,
context={"request": RequestFactory().get("/")}
)
self.assertEqual(
serialiser.data["some-key-you-expect"],
"Some value you expect"
)
Upvotes: 2
Reputation: 88499
Use wsgi_request
(source code-Django) of APIClient
to get the WSGI request object.
self.client = APIClient()
self.client.force_authenticate(user)
res = self.client.get('conference:conference-detail'. args=[conference.id]
# make sure to call the `get(...)` method before accessing `wsgi_request` attribute
request_object = res.wsgi_request
Disclaimer: Not sure whether this is a DRF way to get the request
object.
Upvotes: 3