Как я могу подтвердить свой запрос Аякс и протестировать вывод JSON из функциональных тестов Ruby on Rails?





Используйте ActionDispatch::TestResponse#parsed_body.
Пример:
user = @response.parsed_body
assert_equal "Mike", user['name']
Используйте JSON.parse, который принимает строку в качестве входных данных и возвращает хеш Ruby, который представляет JSON.
Пример:
user = JSON.parse(@response.body)
assert_equal "Mike", user['name']
Также для коротких ответов JSON вы можете просто сопоставить строку JSON с @ response.body. Это избавляет от необходимости полагаться на еще один драгоценный камень.
assert_equal '{"total_votes":1}', @response.body
Rails имеет встроенную поддержку JSON:
def json_response
ActiveSupport::JSON.decode @response.body
end
Нет необходимости в плагине
Тогда вы можете сделать что-то вроде этого:
assert_equal "Mike", json_response['name']
Для повышения производительности вам, вероятно, понадобится что-то вроде: @json_response || = ActiveSupport :: JSON.decode @ response.body
Алекс: Разве это не кэширует ответ первого теста и не возвращает его во всех последующих тестах JSON?
Это кэширует ответ для всех запросов в одной тестовой функции, что может быть нежелательным эффектом. Чтобы уточнить, он не будет кешировать тесты ACROSS.
Если вы используете RSpec, стоит взглянуть на json_spec
Собственно, вы можете неявно использовать модуль JSON:
assert_equal assigns(:user).to_json, @response.body
Вы можете использовать AssertJson драгоценный камень для красивого DSL, который позволяет вам проверять ключи и значения, которые должны присутствовать в вашем ответе JSON.
Добавьте драгоценный камень в свой Gemfile:
group :test do
gem 'assert_json'
end
Это быстрый пример того, как может выглядеть ваш функциональный тест / тест контроллера (пример представляет собой адаптацию их ПРОЧТИ МЕНЯ):
class ExampleControllerTest < ActionController::TestCase
include AssertJson
def test_my_action
get :my_action, :format => 'json'
# => @response.body= '{"key":[{"inner_key":"value1"}]}'
assert_json(@response.body) do
has 'key' do
has 'inner_key', 'value1'
end
has_not 'key_not_included'
end
end
end
Вам просто нужно включить модуль AssertJson в свой тест и использовать блок assert_json, где вы можете проверить ответ на существующие и несуществующие ключи и значения. Подсказка: это не сразу видно в ПРОЧТИ МЕНЯ, но для проверки значения (например, если ваше действие просто возвращает массив строк) вы можете сделать
def test_my_action
get :my_action, :format => 'json'
# => @response.body= '["value1", "value2"]'
assert_json(@response.body) do
has 'value1'
has 'value2'
has_not 'value3'
end
end
Очень хорошо. Я только что внес в него небольшое исправление.
Я не рекомендую использовать этот ДРАГОЦЕННЫЙ КАМЕНЬ. В нем много проблем.
Как уже отмечалось, вы используете JSON.parse для тестирования JSON, но то, где вы выполняете это утверждение, зависит от того, как вы визуализируете JSON.
Если вы генерируете JSON в контроллере, вы анализируете JSON в функциональных тестах контроллера (как показывают другие ответы). Если вы визуализируете JSON с представлением, использующим JBuilder, рабл или другой гем, который использует этот подход, то проанализировать JSON в модульных тестах просмотра не является функциональными тестами контроллера. Модульные тесты, как правило, быстрее выполнять и проще писать - например, вы можете создавать модели в памяти, а не в базе данных.
Ни один из ответов не обеспечивает удобного поддерживаемого способа проверки ответа JSON. Я считаю это лучшим:
https://github.com/ruby-json-schema/json-schema
Это хорошая реализация для стандартного схема json
Вы можете написать такую схему:
schema = {
"type"=>"object",
"required" => ["a"],
"properties" => {
"a" => {
"type" => "integer",
"default" => 42
},
"b" => {
"type" => "object",
"properties" => {
"x" => {
"type" => "integer"
}
}
}
}
}
и используйте его как: JSON::Validator.validate(schema, { "a" => 5 })
Лучший способ проверить это на моей реализации клиента Android.
В более новых версиях rails вы можете использовать parsed_body, чтобы получить к нему доступ в ваших тестах без каких-либо усилий.
Calling parsed_body on the response parses the response body based on the last response MIME type.
Out of the box, only :json is supported. But for any custom MIME types you've registered, you can add your own encoders...
https://api.rubyonrails.org/v5.2.1/classes/ActionDispatch/IntegrationTest.html
С добавлением OpenStruct вы можете печатать немного меньше:
user = JSON.parse(@response.body, object_class: OpenStruct)assert_equal "Mike", user.name