4

我在 Grails 中有一个控制器,它以 JSON 格式返回响应。

我写了一个大致像这样工作的测试

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())
    ...
        }

这按预期工作

Expecting: [{"username":"user","startDate":"2010-11-30"}]
Actual: [{"username":"user","startDate":"2010-11-30"}]

但是,我想知道是否有更好的方法可以在不使用字符串比较的情况下做到这一点。也许可以让我灵活地向响应添加属性而不会使我的测试用例失效?

我可以自己构建它,但我希望在语言中内置某种 JSON 比较。

更新:我尝试直接这样做,没有 toString 并且结果不一致,不太清楚为什么,它在一个阶段工作然后突然得到这个。我看不到我所做的任何会导致差异的代码更改

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: [[], []]
4

3 回答 3

5

您可以使用下面的代码使用GJSON库来比较 json 。

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
    }
}

这也使用少数测试用例进行了测试。如您所见,json 中元素的顺序无关紧要,即 {test1:1,test2:2} 应该与 {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



    }


}

希望有帮助!!!谢谢,

阿努杰·阿内贾

于 2013-09-21T07:39:19.607 回答
1

比较 JSON 值怎么样?

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
}

(你必须使用obj[0]而不是obj因为你返回一个带有 1 个元素的 JSON 数组)

于 2013-09-20T17:29:15.820 回答
1

我用org.skyscreamer.jsonassert.JSONAssert. 很简单:

JSONAssert.assertEquals(expectedJson, json, true)
于 2017-07-19T14:25:32.743 回答