Reputation: 803
I'm trying to implement tests for the Django Rest Framework.
Most of my tests pass and setting them up went smooth, but i'm having an issue now where an assertEqual
never succeeds because it keeps comparing JSON with an OrderedDict.
I have no idea where the OrderedDict comes from since DRF should only return JSON (right?).
Might it be possible that the testing environment is parsing the JSON before comparison? That would suck.
I'm doing an integrated test that only tests the data in the response of a GET request to a certain resource, I do this based on JSON fixtures. I'm not testing a specific component of the REST framework since my implementations of the components are so simple they're already tested by the tests in the DRF project.
Anyways, I hope someone can help me!
Upvotes: 27
Views: 14704
Reputation: 448
You can dump your data into json format :
import json
return HttpResponse(json.dumps(data))
Upvotes: 3
Reputation: 61
I solved the problem by using SerializerMethodField.
Simply, within the serializer class copy next last 3 lines and replace result
with the json member that cause the problem
class ConfigSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Config
fields = ('id', 'url', 'email', "result",)
# COPY NEXT 3 LINES AND CHANGE 'result' WITH THE JSON MEMBER THAT CAUSE THE PROBLEM
result = serializers.SerializerMethodField()
def get_result(self, obj):
return obj.result
Before the result
shows as:
{result: "OrderedDict([('key1', 1), ('key2', OrderedDict([('key3', [1, 2, 3])]))])"}
After solution, result
become:
{"result": {"key1":1,"key2":{"key3":[1,2,3]}}}
Upvotes: 2
Reputation: 1344
As explained here, this is because the default format for requests during tests is multipart
instead of json
. You can specify the format by providing it to your api call like so:
response = self.client.get('/something/1', format='json')
Or you can set the default test request format in your settings.py
like so:
REST_FRAMEWORK = {
'TEST_REQUEST_DEFAULT_FORMAT': 'json', # Use application/json instead of multipart/form-data requests in tests.
}
To fix it for all your tests automagically.
Upvotes: 14
Reputation: 5355
If your tests look something like this:
class SomeTests(APITestCase):
def test_something(self):
response = self.client.get('/something/1')
# assertions with response
Then response will certainly be an OrderedDict rather than a JSON document. Luckily Django 1.9 has introduced the response.json()
method (https://docs.djangoproject.com/en/1.9/topics/testing/tools/#django.test.Response.json) so you can easily convert the response into JSON. Note that you could also use python's json
library.
The catch here is that Django's test client (that DRF extends) is a "dummy browser" (https://docs.djangoproject.com/en/1.9/topics/testing/tools/#the-test-client) and doesn't work exactly like an in-browser framework such as Selenium would. Thus, HTTP calls are actually just simulated HTTP calls that focus on testing your logic and that correct routing/views/serializers/etc. are being used.
Upvotes: 5
Reputation: 312
It sounds like you're using response.data (which returns the parsed json objects) instead of response.content (which gives the raw json string).
See http://www.django-rest-framework.org/api-guide/testing/#testing-responses
Upvotes: 10