Ruby-on-rails 如何使用 RSpec 检查 JSON 响应?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5159882/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 00:33:34  来源:igfitidea点击:

How to check for a JSON response using RSpec?

ruby-on-railsjsonrspec

提问by Fizz

I have the following code in my controller:

我的控制器中有以下代码:

format.json { render :json => { 
        :flashcard  => @flashcard,
        :lesson     => @lesson,
        :success    => true
} 

In my RSpec controller test I want to verify that a certain scenario does receive a success json response so I had the following line:

在我的 RSpec 控制器测试中,我想验证某个场景确实收到了成功的 json 响应,所以我有以下行:

controller.should_receive(:render).with(hash_including(:success => true))

Although when I run my tests I get the following error:

虽然当我运行我的测试时,我收到以下错误:

Failure/Error: controller.should_receive(:render).with(hash_including(:success => false))
 (#<AnnoController:0x00000002de0560>).render(hash_including(:success=>false))
     expected: 1 time
     received: 0 times

Am I checking the response incorrectly?

我是否错误地检查了响应?

回答by zetetic

You can examine the response object and verify that it contains the expected value:

您可以检查响应对象并验证它是否包含预期值:

@expected = { 
        :flashcard  => @flashcard,
        :lesson     => @lesson,
        :success    => true
}.to_json
get :action # replace with action name / params as necessary
response.body.should == @expected

EDIT

编辑

Changing this to a postmakes it a bit trickier. Here's a way to handle it:

将其更改为 apost会使它变得有点棘手。这是一种处理方法:

 it "responds with JSON" do
    my_model = stub_model(MyModel,:save=>true)
    MyModel.stub(:new).with({'these' => 'params'}) { my_model }
    post :create, :my_model => {'these' => 'params'}, :format => :json
    response.body.should == my_model.to_json
  end

Note that mock_modelwill not respond to to_json, so either stub_modelor a real model instance is needed.

请注意,mock_model不会响应to_json,因此需要stub_model一个真实的模型实例。

回答by brentmc79

You could parse the response body like this:

您可以像这样解析响应正文:

parsed_body = JSON.parse(response.body)

Then you can make your assertions against that parsed content.

然后,您可以对该解析的内容进行断言。

parsed_body["foo"].should == "bar"

回答by lightyrs

Building off of Kevin Trowbridge's answer

基于凯文·特罗布里奇的回答

response.header['Content-Type'].should include 'application/json'

回答by acw

There's also the json_specgem, which is worth a look

还有json_specgem,值得一看

https://github.com/collectiveidea/json_spec

https://github.com/collectiveidea/json_spec

回答by Chitrank Samaiya

Simple and easy to way to do this.

简单易行的方法来做到这一点。

# set some variable on success like :success => true in your controller
controller.rb
render :json => {:success => true, :data => data} # on success

spec_controller.rb
parse_json = JSON(response.body)
parse_json["success"].should == true

回答by Lorem Ipsum Dolor

You can also define a helper function inside spec/support/

你也可以在里面定义一个辅助函数 spec/support/

module ApiHelpers
  def json_body
    JSON.parse(response.body)
  end
end

RSpec.configure do |config| 
  config.include ApiHelpers, type: :request
end

and use json_bodywhenever you need to access the JSON response.

json_body在您需要访问 JSON 响应时使用。

For example, inside your request spec you can use it directly

例如,在您的请求规范中,您可以直接使用它

context 'when the request contains an authentication header' do
  it 'should return the user info' do
    user  = create(:user)
    get URL, headers: authenticated_header(user)

    expect(response).to have_http_status(:ok)
    expect(response.content_type).to eq('application/vnd.api+json')
    expect(json_body["data"]["attributes"]["email"]).to eq(user.email)
    expect(json_body["data"]["attributes"]["name"]).to eq(user.name)
  end
end

回答by Clinton

Another approach to test just for a JSON response (not that the content within contains an expected value), is to parse the response using ActiveSupport:

另一种仅测试 JSON 响应(不是其中的内容包含预期值)的方法是使用 ActiveSupport 解析响应:

ActiveSupport::JSON.decode(response.body).should_not be_nil

If the response is not parsable JSON an exception will be thrown and the test will fail.

如果响应不可解析 JSON,则会抛出异常并且测试将失败。

回答by Kevin Trowbridge

You could look into the 'Content-Type'header to see that it is correct?

您可以查看'Content-Type'标题以查看它是否正确?

response.header['Content-Type'].should include 'text/javascript'

回答by Koen.

When using Rails 5 (currently still in beta), there's a new method, parsed_bodyon the test response, which will return the response parsed as what the last request was encoded at.

当使用 Rails 5(目前仍处于测试阶段)时,有一个新方法,parsed_body在测试响应上,它将返回解析为最后一个请求编码的响应。

The commit on GitHub: https://github.com/rails/rails/commit/eee3534b

GitHub 上的提交:https: //github.com/rails/rails/commit/eee3534b

回答by Damien Roche

If you want to take advantage of the hash diff Rspec provides, it is better to parse the body and compare against a hash. Simplest way I've found:

如果您想利用 Rspec 提供的散列差异,最好解析正文并与散列进行比较。我发现的最简单的方法:

it 'asserts json body' do
  expected_body = {
    my: 'json',
    hash: 'ok'
  }.stringify_keys

  expect(JSON.parse(response.body)).to eql(expected_body)
end