Как проверить ответ JSON с помощью RSpec? - PullRequest
139 голосов
/ 01 марта 2011

В моем контроллере есть следующий код:

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

В моем тесте контроллера RSpec я хочу убедиться, что определенный сценарий действительно получает ответ json, поэтому у меня была следующая строка:

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

Хотя, когда я запускаю свои тесты, я получаю следующую ошибку:

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

Я неправильно проверяю ответ?

Ответы [ 11 ]

161 голосов
/ 02 марта 2011

Вы можете проверить объект ответа и убедиться, что он содержит ожидаемое значение:

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

РЕДАКТИРОВАТЬ

Изменение этого значения на post делает егонемного сложнее.Вот способ справиться с этим:

 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

Обратите внимание, что mock_model не будет отвечать на to_json, поэтому необходим либо stub_model, либо реальный экземпляр модели.

153 голосов
/ 07 марта 2011

Вы можете проанализировать тело ответа следующим образом:

parsed_body = JSON.parse(response.body)

Затем вы можете сделать свои утверждения относительно этого проанализированного содержимого.

parsed_body["foo"].should == "bar"
45 голосов
/ 26 апреля 2012

Здание от Ответ Кевина Троубриджа

response.header['Content-Type'].should include 'application/json'
34 голосов
/ 01 августа 2011

Также есть json_spec драгоценный камень, который стоит посмотреть

https://github.com/collectiveidea/json_spec

11 голосов
/ 22 марта 2013

Простой и легкий способ сделать это.

# 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
7 голосов
/ 19 февраля 2017

Вы также можете определить вспомогательную функцию внутри spec/support/

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

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

и использовать json_body всякий раз, когда вам нужен доступ к ответу JSON.

Например, внутри спецификации запросаВы можете использовать его напрямую

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
7 голосов
/ 15 ноября 2012

Другой подход к проверке только для ответа JSON (не то, что содержимое внутри содержит ожидаемое значение), заключается в анализе ответа с помощью ActiveSupport:

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

Если ответ не может быть обработан JSON, будет сгенерировано исключение и тест не пройден.

7 голосов
/ 20 марта 2012

Вы можете заглянуть в заголовок 'Content-Type', чтобы убедиться, что он правильный?

response.header['Content-Type'].should include 'text/javascript'
4 голосов
/ 16 марта 2016

При использовании Rails 5 (в настоящее время все еще в бета-версии), есть новый метод, parsed_body в ответе теста, который будет возвращать проанализированный ответ как то, в котором был закодирован последний запрос.

Фиксацияна GitHub: https://github.com/rails/rails/commit/eee3534b

1 голос
/ 18 марта 2019

Если вы хотите воспользоваться преимуществами хеша, которые предоставляет Rspec, лучше проанализировать тело и сравнить с хешем.Простейший способ, который я нашел:

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

  expect(JSON.parse(response.body)).to eql(expected_body)
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...