如何测试 Ruby on Rails 功能测试的 JSON 结果?

如何断言我的 阿贾克斯请求并测试 Ruby on Rails 功能测试的 JSON 输出?

40903 次浏览

在 Rails 中 > = 5

使用 ActionDispatch::TestResponse#parsed_body

例如:

user = @response.parsed_body
assert_equal "Mike", user['name']

在 Rails 中直到4. x

使用 JSON.parse,它接受一个字符串作为输入,并返回 JSON 表示的 Ruby 散列。

例如:

user = JSON.parse(@response.body)
assert_equal "Mike", user['name']

对于简短的 JSON 响应,您可以简单地将 JSON 的字符串与@response 匹配。尸体。这就避免了不得不依赖另一颗宝石。

assert_equal '{"total_votes":1}', @response.body

Rails 内置了对 JSON 的支持:

def json_response
ActiveSupport::JSON.decode @response.body
end

不需要插件

然后你可以这样做:

assert_equal "Mike", json_response['name']

如果您正在使用 RSpec,那么 Json _ spec值得一看

Https://github.com/collectiveidea/json_spec

实际上,您可以隐式地使用 JSON 模块:

assert_equal assigns(:user).to_json, @response.body

您可以使用 断言 Json 宝石作为一个很好的 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,视图使用 建筑工人Rabl或其他采用这种方法的 gem,那么 在视图单元测试中解析 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在测试中访问它,而不需要做任何工作。

在响应上调用 parsed _ body 将根据最后一个响应 MIME 类型解析响应正文。

开箱即用,只支持: json。但是对于您已经注册的任何自定义 MIME 类型,您可以添加您自己的编码器..。

Https://api.rubyonrails.org/v5.2.1/classes/actiondispatch/integrationtest.html