Подтвердить что ты не робот

Как использовать символы кода состояния HTTP в RSpec?

Я использую символы кода состояния HTTP в коде контроллера, например:

render json: {
    auth_token: user.authentication_token, 
    user: user
  }, 
  status: :created

или

render json: {
    errors: ["Missing parameter."]
  }, 
  success: false, 
  status: :unprocessable_entity

В коде моей спецификации запроса я также хотел бы использовать символы:

post user_session_path, email: @user.email, password: @user.password
expect(last_response.status).to eq(201)

...

expect(last_response.status).to eq(422)

Однако каждый тест, в котором я использую символы вместо целых чисел, терпит неудачу:

Failure/Error: expect(last_response.status).to eq(:created)

  expected: :created
       got: 201

  (compared using ==)

Вот последний список Символы кода состояния HTTP в стойке.

4b9b3361

Ответ 1

С одной стороны, ответ строится с помощью таких методов, как:

  • успех?

  • перенаправлять?

  • unprocessable?

  • полный список: response.methods.grep(/\?/)

С другой стороны, предикаты Rspec преобразует каждый метод foo? в be_foo.

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

Только те тесты Note Rails полагаются на несколько статусов.

Ответ 2

это работает для меня:

expect(response.response_code).to eq(Rack::Utils::SYMBOL_TO_STATUS_CODE[:not_found])

Ответ 3

Объект response отвечает на несколько типов символов в виде сообщений. Поэтому вы можете просто:

expect(response).to be_success
expect(response).to be_error
expect(response).to be_missing
expect(response).to be_redirect

Для других типов, таких как :created, вы можете создать простой пользовательский макет для этого, который обертывает assert_response:

RSpec::Matchers.define :have_status do |type, message = nil|
  match do |_response|
    assert_response type, message
  end
end

expect(response).to have_status(:created)
expect(response).to have_status(404)

Это должно работать нормально для спецификаций контроллера, которые имеют правильную настройку состояния. Он будет не работать для спецификаций функций. Я не пробовал со спецификациями запросов, поэтому ваше перемещение может варьироваться.

Причина этого заключается в том, что он использует тот факт, что спецификации контроллера RSpec имеют аналогичную настройку состояния за кулисами. Поэтому, когда assert_response обращается к @response, он доступен.

Этот помощник, вероятно, может быть улучшен путем простого копирования кода, используемого assert_response в соединитель:

RSpec::Matchers.define :have_status do |type, message = nil|
  match do |response|
    if Symbol === type
      if [:success, :missing, :redirect, :error].include?(type)
        response.send("#{type}?")
      else
        code = Rack::Utils::SYMBOL_TO_STATUS_CODE[type]
        response.response_code == code
      end
    else
      response.response_code == type
    end
  end

  failure_message do |response|
    message or
      "Expected response to be a <#{type}>, but was <#{response.response_code}>"
  end
end

ОБНОВЛЕНИЕ: 2014-07-02

Теперь это доступно из коробки с RSpec Rails 3: https://www.relishapp.com/rspec/rspec-rails/v/3-0/docs/matchers/have-http-status-matcher

Ответ 4

С rspec-rails (по rspec v3.0) можно использовать

expect(response).to have_http_status(:created)