I have a controller in Grails that is returning a response in JSON.
I have written a test which works roughly like this
test(){
def expectedResponse=JSON.parse('[{"username":"user","startDate":"2010-11-30"}]')
...
def actualResponse=JSON.parse(response.text)
println "Expecting: ${expectedResponse.toString()}"
println "Actual: ${actualResponse.toString()}"
assertEquals(expectedResponse.toString(), actualResponse.toString())
...
}
This works as expected
Expecting: [{"username":"user","startDate":"2010-11-30"}]
Actual: [{"username":"user","startDate":"2010-11-30"}]
However, I was wondering if there was a better way to do this without resorting to a string comparison.. Perhaps something that could leave me the flexibility to be able to add attributes to the response without invalidating my test case?
I could build this myself, but I would've expected some sort of JSON comparison to be built into the language.
Update: I tried doing this directly, without the toString and have had inconsistent results, not quite sure why, it was working at one stage then suddenly got this. I can't see any code changes I made that would've caused the difference
groovy.lang.MissingMethodException: No signature of method: com.siggysale.MainControllerTests.assertEquals() is applicable for argument types: (org.codehaus.groovy.grails.web.json.JSONArray, org.codehaus.groovy.grails.web.json.JSONArray) values: [[], []]
You can compare json using GJSON libraray using the code below.
class GJsonUtil {
static Boolean compareJsonStrings(String obj1, String obj2){
JsonParser parser = new JsonParser();
JsonElement o1 = parser.parse(obj1)
JsonElement o2 = parser.parse(obj2)
return o1==o2
}
}
This is also tested using few test cases. As you can see order of element in a json doesn't matter i.e. {test1:1,test2:2} should be same as {test2:2,test1:1}.
class GJsonSpec extends UnitSpec {
@Unroll("#ID : comparing two json")
def "Comparing json string"() {
setup:
when:
def json1String = (obj1 as JSON).toString()
def json2String = (obj2 as JSON).toString()
println "json1String=${json1String}"
println "json2String=${json2String}"
def match=GJsonUtil.compareJsonStrings(json1String,json2String)
then:
match==result
where:
ID | obj1 | obj2 | result
1 | [a: 1, b: [c: 1, d: 2]] | [b: [c: 1, d: 2], a: 1] | true
2 | [a: 1, b: [c: 1, d: 3]] | [b: [c: 1, d: 2], a: 1] | false
3 | [a: 2, b: [c: 1, d: 2]] | [b: [c: 1, d: 2], a: 1] | false
4 | [a: 1, b: [d: 1, c: 2]] | [b: [d: 1, c: 2], a: 1] | true
5 | [a: 1, b: [d: [x:"ram",y:"Laxman"], c: 2]] | [b: [d: [x:"ram",y:"Laxman"], c: 2], a: 1] | true//deep json comparision
6 | [a: 1, b: [d: [x:"Ram",y:"Laxman"], c: 2]] | [b: [d: [x:"ram",y:"laxman"], c: 2], a: 1] | false//deep json comparision+ lower/uppercase
7 | [a: 1, b: [d: [x:"Ram",y:["test1","test2","test3"]], c: 2]] | [b: [d: [x:"Ram",y:["test1","test3","test2"]], c: 2], a: 1] | false//deep json comparision+ lower/uppercase
8 | [a: ["test1","test2","test3"]] | [a:["test1","test2","test3"] ] | true//comaparing list order
9 | [a: ["test1","test2","test3"]] | [a:["test1","test3","test2"] ] | false//comaparing list order should fail
10|[:]|null|false
11|null|[:]|false
12|null|null|true
13|[a: ["test1",null,"test3"]] | [a:["test1",null,"test3"] ] | true//comaparing nulls in json
}
}
Hope that helps!!! Thanks,
Anuj Aneja
How about comparing JSON values?
import groovy.json.JsonSlurper
def test() {
def obj = new JsonSlurper().parseText(response.text)
assert obj[0].username == "user"
assert obj[0].startDate == "2010-11-30"
// make sure there isn't any other data
assert obj.size() == 1
assert obj[0].size() == 2
}
(you have to use obj[0]
instead of obj
because you are returning a JSON array with 1 element)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With