У меня есть следующий код в моем контроллере:
format.json { render :json => {
:flashcard => @flashcard,
:lesson => @lesson,
:success => true
}
В моем тесте контроллера RSpec я хочу убедиться, что определенный сценарий действительно получил ответ json, поэтому у меня была следующая строка:
controller.should_receive(:render).with(hash_including(:success => true))
Хотя, когда я запускаю свои тесты, я получаю следующую ошибку:
Failure/Error: controller.should_receive(:render).with(hash_including(:success => false))
(#<AnnoController:0x00000002de0560>).render(hash_including(:success=>false))
expected: 1 time
received: 0 times
Я неправильно проверяю ответ?
ruby-on-rails
json
rspec
шипение
источник
источник
post :create
с действительным хешем параметров.post :create, :format => :json
{"a":"1","b":"2"}
и{"b":"2","a":"1"}
не равные строки, которые записывают равные объекты. Вы не должны сравнивать строки, но объекты,JSON.parse('{"a":"1","b":"2"}').should == {"a" => "1", "b" => "2"}
вместо этого.Вы можете разобрать тело ответа следующим образом:
Затем вы можете сделать свои утверждения против этого проанализированного контента.
источник
b = JSON.parse(response.body, symoblize_names: true)
чтобы получить к ним доступ, используя следующие символы:b[:foo]
Построение ответа Кевина Троубриджа
источник
Mime::JSON
вместо'application/json'
?Mime::JSON.to_s
Также есть драгоценный камень json_spec , который стоит посмотреть
https://github.com/collectiveidea/json_spec
источник
Простой и легкий способ сделать это.
источник
Вы также можете определить вспомогательную функцию внутри
spec/support/
и использовать
json_body
всякий раз, когда вам нужно получить доступ к ответу JSON.Например, в спецификации вашего запроса вы можете использовать его напрямую
источник
Другой подход к тестированию только для ответа JSON (не то, что содержимое внутри содержит ожидаемое значение), заключается в анализе ответа с помощью ActiveSupport:
Если ответ не может быть обработан JSON, будет сгенерировано исключение и тест не пройден.
источник
Вы могли бы заглянуть в
'Content-Type'
заголовок, чтобы увидеть, что это правильно?источник
render :json => object
, я считаю Rails возвращает Content-Type заголовок «приложения / JSON».response.header['Content-Type'].should match /json/
При использовании Rails 5 (в настоящее время все еще в бета-версии)
parsed_body
в тестовом ответе есть новый метод , который будет возвращать проанализированный ответ как то, в котором был закодирован последний запрос.Коммит на GitHub: https://github.com/rails/rails/commit/eee3534b
источник
#parsed_body
. Это еще не задокументировано, но, по крайней мере, формат JSON работает. Обратите внимание, что ключи по-прежнему являются строками (а не символами), поэтому можно найти один из них#deep_symbolize_keys
или#with_indifferent_access
полезный (мне нравится последний).Если вы хотите воспользоваться преимуществами хеша diff, предоставляемого Rspec, лучше проанализировать тело и сравнить с хешем. Самый простой способ, который я нашел:
источник
JSON сравнительное решение
Получает чистый, но потенциально большой Diff:
Пример вывода консоли из реальных данных:
(Спасибо комментарий @floatingrock)
Решение для сравнения строк
Если вы хотите получить железное решение, вам следует избегать использования парсеров, которые могут вводить ложноположительное равенство; сравните тело ответа со строкой. например:
Но это второе решение менее визуально дружественное, поскольку оно использует сериализованный JSON, который будет содержать множество экранированных кавычек.
Индивидуальное решение для соответствия
Я стремлюсь написать собственный сопоставитель, который намного лучше точно определяет, в каком именно рекурсивном слоте пути JSON различаются. Добавьте следующее к своим макросам rspec:
Пример использования 1:
Пример использования 2:
Пример вывода:
Другой пример выходных данных для демонстрации несоответствия в глубине вложенного массива:
Как вы можете видеть, вывод сообщает вам ТОЧНО, где исправить ожидаемый JSON.
источник
Я нашел совпадение клиентов здесь: https://raw.github.com/gist/917903/92d7101f643e07896659f84609c117c4c279dfad/have_content_type.rb
Поместите его в spec / support / matchers / have_content_type.rb и убедитесь, что загружаете из поддержки что-то вроде этого в вашем spec / spec_helper.rb
Вот сам код, на тот случай, если он исчез из указанной ссылки.
источник
Многие из приведенных выше ответов несколько устарели, так что это краткое резюме для более поздней версии RSpec (3.8+). Это решение не вызывает предупреждений от rubocop-rspec и соответствует рекомендациям rspec :
Успешный ответ JSON определяется двумя факторами:
application/json
Предполагая, что объект ответа является анонимным субъектом теста, оба вышеперечисленных условия могут быть проверены с использованием встроенных сопоставителей Rspec:
Если вы готовы назвать свою тему, вышеприведенные тесты можно упростить:
источник