What is the best strategy when trying to validate big JSON responses inside DRF unit tests?
For example:
class MyUnitTest(APITestCase):
def some_unit_test(self):
response = self.client.get(reverse('url'), data, format='json')
This method can return a big response with varying data inside it which I would like to verify. Should I just 'hardcode' the expected response for each method call? Or there is a more 'smart' way of generating the expected response and doing this assertion?
Thanks!
Related
All I know is that JSONResponse is HttpResponse with content_type="application/JSON"
And JSONRenderer will convert the python dictionary data to JSON format
Do they do the same work? Or is there any difference between them.
I've read the difference between JSONParser and JSONRenderer which doesn't really solve my problem
JSONResponse and JSONRenderer are quite similar and perform largely the same action. Both format server responses in JSON, however their usage differs.
Both convert plain Python data to JSON format through the use of json.dumps and send the output back to the client. See JSONRenderer source and JSONResponse source for the code.
In terms of their difference, a JSONResponse should be returned by a view method in generic Django to send data with the header Content-Type: application/json. JSONRenderer on the other hand is used in Django Rest Framework to format serialized data to JSON format depending on the accept header in the received request. Check the documentation on Django request-responses: (https://docs.djangoproject.com/en/2.1/ref/request-response/) or the docs on DRF renderers (http://www.django-rest-framework.org/api-guide/renderers/) for more on their usage.
As an example a JSONResponse might be used like this:
def some_view(request):
data = get_data()
return JSONResponse(data)
And usage for JSONRenderer in settings.py:
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.JSONRenderer', 'rest_framework.renderers.BrowsableAPIRenderer'
)
}
The above will render response data for routes using Django Rest Framework in JSON depending on the accept header of the request.
As my json request contains all mandatory parameters in request body, I want to validate all parameters using Jmeter.
Do let me know if it is possible to validate all request parameters presents in json body using jmeter or jmeter plugins
Normally people are interested in validating responses, not the requests therefore I am not aware of any suitable Test Elements either bundled or available via Plugins. For responses validation you have JSON Path Assertion
If for some reason you need to validate the request and fail the sampler if the validation fails you can use JSR223 Post Processor. Example code:
def request = sampler.getArguments().getArgument(0).getValue()
def json = new groovy.json.JsonSlurper().parseText(request)
// do any checks you need, for example
if (!json.keySet().contains("somekey")) {
log.info("Key \"somekey\" was not found in the request")
prev.setSuccessful(false)
}
References:
JsonSlurper
Parsing and producing JSON
Groovy Is the New Black
I'm developing a REST API using Cloud Endpoints. I know that as per the documentation each API method should return an entity that is then automatically converted to a valid JSON string.
However, I'm dealing with an authentication library that in some cases returns a JSON which should be passed back to the client as a response.
Sticking with the default approach, meaning returning an entity, would still be possible, but it would involve a number of obnoxious intermediate steps, like parsing the JSON and filling the right fields of the entity to be returned according to the JSON content.
I was wondering if there is a more straightforward way to instruct the API to directly return the JSON string, instead of converting it to an entity just to have it translated back to the source JSON.
One thing that probably may help you.
Suppose you have a RPC response class as
from protorpc import messages
from protorpc import message_types
from protorpc import remote
class ApiResponse(message.Messages):
response = messages.StringField(1, required = True)
You can return your JSON in response field by using JSON module. First of all import json in your endpoints api
import json
Suppose your response is
json_response = [{'name': 'Jack', 'age':12}, {'name': 'Joe', 'age':13}]
In your response to this api you can do this:-
return ApiResponse(response = json.dumps({'data': json_response}))
json.dumps() converts your dictionary object into JSON string that can be passed to response of ApiResponse class.
After you receive response in client side(javascript), you can simply parse it to JSON using
JSON.parse(response)
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!
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.
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
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.
You can dump your data into json format :
import json
return HttpResponse(json.dumps(data))
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]}}}
I have a question regarding REST Assured. - https://code.google.com/p/rest-assured/wiki/Usage
I understand that I can use REST assured to make HTTP calls(.get .put etc.) and validate the response using when() etc. I would like to validate JSON responses that I have already saved in the database, instead of Calling the web service realtime and validating it's response.
Can I use REST-assured to Load a JSON response as a String and validate it?
Yes you can use Rest Assured's JsonPath project independently of Rest Assured (see getting started page). Once you have it in classpath you can do something like this:
JsonPath jsonPath = new JsonPath(<your json as string>);
String title = jsonPath.getString("x.y.title");