Вопрос по human-readable, ruby-on-rails, http-status-codes, rspec – Как использовать символы кода статуса HTTP в RSpec?

26

я используюСимволы кода состояния 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 в стойке.

Ваш Ответ

4   ответа
11

успех?

перенаправление?

unprocessable?

Полный список сделать:response.methods.grep(/\?/)

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

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

Примечание только для Rails testполагаться на несколько статусов.

это не помогает? apneadiving
Без обид, пожалуйста. Я последний, кто забывает голосовать за людейс помощью. Хотя обычно я жду, пока я полностью не решу проблему, прежде чем я проголосую или предоставлю флаг ответа. JJD
Я старалсяexpect(last_response.status).to be_created который терпит неудачу с "неопределенный метод `создан? ' для 201: Fixnum ". JJD
Так же:expect(last_response.status).to be_success не с "неопределенный метод 'успех? на 201: Fixnum ", Я понял этоcreated? не является частью списка и экспериментировал с пользовательским соответствием ... пока без успеха. JJD
20

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

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

8

СRSpec рельсы (по состоянию наRSpec 3) этоможно использовать

expect(response).to have_http_status(:created)

Обновление 2018-06-11:

Начиная с Rails 6, некоторые из сопоставителей будут заменены (например,success отsuccessful).

Только в версии 3 RSpec или позже.have_http_status не входит в RSpec 2. Tinynumbers
20

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

Похожие вопросы