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


Answers:


86

使用JSON gem的JSON.parse,它将字符串作为输入并返回JSON表示的Ruby哈希。

这是测试的基本要点:

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

这是gem的文档:http : //json.rubyforge.org/。另外,您可以非常轻松地在IRB中使用JSON gem 。


通过添加OpenStruct,您可以减少键入操作:user = JSON.parse(@response.body, object_class: OpenStruct) assert_equal "Mike", user.name
Jimmy Bosse

90

Rails内置了JSON支持:

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

无需插件

然后,您可以执行以下操作:

assert_equal "Mike", json_response['name']

3
为了提高性能,您可能需要类似:@json_response || = ActiveSupport :: JSON.decode @ response.body
Alex Neth

6
Alex:不会缓存第一个测试的响应并在随后的所有JSON测试中返回它吗?
iGEL 2011年

2
这将在一个测试功能中缓存所有请求的响应,这可能不是理想的效果。需要说明的是,它不会缓存ACROSS测试。
WattsInABox 2011年


4

同样,对于简短的JSON响应,您只需将JSON的字符串与@ response.body匹配即可。这避免了不得不依赖另一个宝石。

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


1

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

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

1

如前所述,您使用JSON.parse来测试JSON,但是执行该声明的位置取决于呈现JSON的方式。

如果要在控制器中生成JSON,请在控制器功能测试中解析JSON(如其他答案所示)。如果要渲染JSON,并在使用Jbuilderrabl或采用此方法的其他gem的视图中进行渲染,则在视图单元测试而非控制器功能测试中解析JSON。单元测试通常执行起来更快,更容易编写-例如,您可以在内存中构建模型,而不是在数据库中创建模型。


1

没有一个答案提供了一种很好的可维护方式来验证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客户端实现进行验证的最佳方法。


-1

您可以将AssertJson gem用于一个不错的DSL,它可以让您检查JSON响应中应该存在的键和值。

将宝石添加到您的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

非常好。我刚刚为它做了一些小错误修正。
gertas 2014年

1
我建议不要使用该GEM。它有很多问题。
扎克2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.