2013-09-20 6 views
3

У меня есть контроллер в Grails, который возвращает ответ в JSON.Как сравнить JSON в тесте grails

Я написал тест, который работает примерно как этот

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

Рассуждая об этом снова, я думаю, что сравнение строк, вероятно, хороший подход по большей части –

+2

Вы просто должны быть в состоянии сравнить '' expectedResponse' и actualResponse', нет? –

+0

@tim_yates очень странно, в первый раз я пробовал, что это не сработало, казалось, жаловался на то, что не смог утвердитьEquals два массива (из памяти) ... Теперь я просто попробовал это снова, забрав toString() компонент в этом образце, и он работал ... не знаю, что произошло в первый раз –

ответ

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 потому, что вы возвращаете массив JSON с 1 элемент)

+0

hi micha, да, я подумал об этом, но я подумал, что лучше иметь строчную версию моего ожидаемого JSON в тесте, чтобы сравнить его, просто чтобы быть визуально визуально, если ничего больше –

+1

Проблема со строками в том, что ваш тест может выйти из строя, даже если ответ вашего контроллера действителен. Что делать, если порядок свойств изменяется, а 'startDate' возвращается до' username'? В дополнение к этому становится очень раздражающим, если контроллер возвращает большее количество json, и вы хотите проверить только определенные части ответа. Вы также не можете определить, какое поле вызвало проблему, вам всегда нужно посмотреть на полную строку json, чтобы найти ошибку, если тест завершился неудачно. – micha

+0

Да, я полностью согласен с вами там .. Мне действительно нужно что-то посередине, сравните эту ожидаемую строку JSON с этим ответом JSON, но игнорируйте дополнительные атрибуты и порядок. Я видел подобный тип синтаксиса, сделанный с картами, поэтому Мне было интересно, возможно ли это с помощью JSON –

5

можно сравнить с использованием JSON GJSON libraray, используя этот код.

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 



    } 


} 

Надеюсь, что поможет !!! Спасибо,

Anuj Aneja

0

Я использую org.skyscreamer.jsonassert.JSONAssert. Есть в простой, как:

JSONAssert.assertEquals(expectedJson, json, true) 
Смежные вопросы