【发布时间】:2008-12-03 10:07:30
【问题描述】:
如何断言我的 Ajax 请求并测试来自 Ruby on Rails 功能测试的 JSON 输出?
【问题讨论】:
标签: ruby-on-rails json tdd
如何断言我的 Ajax 请求并测试来自 Ruby on Rails 功能测试的 JSON 输出?
【问题讨论】:
标签: ruby-on-rails json tdd
使用ActionDispatch::TestResponse#parsed_body。
例子:
user = @response.parsed_body
assert_equal "Mike", user['name']
使用JSON.parse,它将字符串作为输入并返回 JSON 表示的 Ruby 哈希。
例子:
user = JSON.parse(@response.body)
assert_equal "Mike", user['name']
【讨论】:
user = JSON.parse(@response.body, object_class: OpenStruct)assert_equal "Mike", user.name
Rails 内置了 JSON 支持:
def json_response
ActiveSupport::JSON.decode @response.body
end
不需要插件
然后你可以这样做:
assert_equal "Mike", json_response['name']
【讨论】:
如果您使用的是 RSpec,json_spec 值得一看
【讨论】:
对于简短的 JSON 响应,您可以简单地将 JSON 字符串与@response.body 匹配。这样可以避免不得不依赖另一个 gem。
assert_equal '{"total_votes":1}', @response.body
【讨论】:
在较新版本的 Rails 中,您可以利用 parsed_body 在您的测试中无需任何工作即可访问它。
在响应上调用 parsed_body 会根据最后一个响应的 MIME 类型解析响应正文。
开箱即用,仅支持 :json。但是对于您注册的任何自定义 MIME 类型,您可以添加自己的编码器...
https://api.rubyonrails.org/v5.2.1/classes/ActionDispatch/IntegrationTest.html
【讨论】:
没有一个答案提供了一种很好的可维护方式来验证 JSON 响应。我觉得这个是最好的:
https://github.com/ruby-json-schema/json-schema
它为标准json schema提供了一个很好的实现
您可以编写如下架构:
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 客户端实现验证它的最佳方式。
【讨论】:
其实你可以隐式使用 JSON 模块:
assert_equal assigns(:user).to_json, @response.body
【讨论】:
如上所述,您使用 JSON.parse 来测试 JSON,但执行该断言的位置取决于您呈现 JSON 的方式。
如果您在控制器中生成 JSON,则在控制器功能测试中解析 JSON(如其他答案所示)。如果您使用 Jbuilder、rabl 或其他采用这种方法的 gem 来渲染 JSON,那么 parse the JSON in the view unit tests 不是控制器功能测试。单元测试通常执行起来更快,更容易编写 - 例如,您可以在内存中构建模型,而不是在数据库中创建它们。
【讨论】:
您可以将AssertJson gem 用于一个不错的 DSL,它允许您检查 JSON 响应中应该存在的键和值。
将 gem 添加到您的 Gemfile:
group :test do
gem 'assert_json'
end
这是一个简单的示例,您的功能/控制器测试可能是什么样子(该示例改编自他们的README):
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 块,您可以在其中检查存在和不存在的键和值的响应。提示:它在README 中不会立即可见,但要检查一个值(例如,如果您的操作只返回一个字符串数组),您可以这样做
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
【讨论】: