Arhn - архитектура программирования

Как сравнить JSON в тесте Grails

У меня есть контроллер в 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: [[], []]
20.09.2013

  • Подумав об этом еще раз, я думаю, что сравнение строк, вероятно, является хорошим подходом по большей части. 20.09.2013
  • Вы просто должны уметь сравнивать expectedResponse и actualResponse, нет? 20.09.2013
  • @tim_yates очень странно, в первый раз, когда я попробовал это, это не сработало, казалось, он жаловался на невозможность утверждения двух массивов (из памяти) ... Теперь я только что попробовал еще раз, убрав компонент toString () в этом образце, и это сработало... понятия не имею, что произошло в первый раз 23.09.2013
  • Хорошо, поцарапайте, что это происходит снова, я получаю это при прямом сравнении, т.е. .web.json.JSONArray, org.codehaus.groovy.grails.web.json.JSONArray) 24.09.2013
  • ты не можешь assert expectedResponse == actualResponse 24.09.2013
  • хммм.. хорошо, я только что попробовал assertTrue(expectedResponse == factResponse) и это сработало, но я также пробовал тестировать с использованием assertEquals(expectedResponse,actualResponse) и на этот раз это сработало... Я получаю очень противоречивые результаты с этим я handn иначе не изменил эти тесты, так что я действительно не могу это объяснить 25.09.2013
  • фу, в моем компиляторе должна быть какая-то ошибка для другого теста.. только что получил это сообщение Нет подписи метода: com.myproj.MainControllerTests.assertEquals() применим для типов аргументов: (java.lang.Integer, .lang.Integer): [10, 0], сделал незначительное изменение пробела, а затем сохранил и скомпилировал, и все исчезло. 25.09.2013

Ответы:


1

Вы можете сравнить json с помощью библиотеки GJSON, используя приведенный ниже код.

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



    }


}

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

Ануй Анеха

21.09.2013

2

Как насчет сравнения значений 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 элементом)

20.09.2013
  • привет Миша, да, я думал об этом, но я подумал, что лучше иметь строковую версию моего ожидаемого JSON в тесте, чтобы сравнить его, просто чтобы быть ясным визуально, если ничего другого 23.09.2013
  • Проблема со строками заключается в том, что ваш тест может завершиться ошибкой, даже если ответ вашего контроллера действителен. Что, если порядок свойств изменится и startDate будет возвращено раньше username? В дополнение к этому становится очень раздражающим, если контроллер возвращает большое количество json, а вы хотите проверить только определенные части ответа. Вы также не можете сказать, какое поле вызвало проблему, вам всегда нужно смотреть на полную строку json, чтобы найти ошибку, если тест не пройден. 23.09.2013
  • да, я полностью с вами согласен. Мне действительно нужно что-то среднее, сравните эту ожидаемую строку JSON с этим ответом JSON, но игнорируйте дополнительные атрибуты и порядок.. Я видел похожий классный синтаксис, выполненный с картами, поэтому я было интересно, возможно ли это с JSON 24.09.2013
  • Когда вы говорите о заводном, это должен быть принятый ответ. Нет необходимости во внешних библиотеках, потому что сравнение результатов JsonSlurper делает то же самое! 14.10.2015

  • 3

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

    JSONAssert.assertEquals(expectedJson, json, true)
    
    19.07.2017
    Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..