RSpe c: метод контроллера заглушки в спецификации запроса - PullRequest
1 голос
/ 19 марта 2020

Я пишу RSpe c запрос spe c, который выглядит примерно так (несколько сокращенно для краткости):

describe 'Items', type: :request do
  describe 'GET /items' do
    before do
      allow_any_instance_of(ItemsController).to receive(:current_user).and_return(user)
      get '/items'
      @parsed_body = JSON.parse(response.body)
    end

    it 'includes all of the items' do
      expect(@parsed_body).to include(item_1)
      expect(@parsed_body).to include(item_2)
    end
  end
end

Контроллер выглядит так:

class ItemsController < ApplicationController
  before_action :doorkeeper_authorize!
  def index
    render(json: current_user.items)
  end
end

Как видите, я пытаюсь заглушить метод привратника current_user.

Тесты в настоящее время проходят, и контроллер работает, как и ожидалось. У меня вопрос по поводу строки:

allow_any_instance_of(ItemsController).to receive(:current_user).and_return(user)

Я написал эту строку на основе ответов в Как заглушить метод ApplicationController в запросе spe c, и он работает. Тем не менее, документы RSpe c называют это "запахом кода" и rubocop-rspec жалуются, "RSpec/AnyInstance: Avoid stubbing using allow_any_instance_of".

Одной из альтернатив будет получение ссылки на контроллер и используйте instance_double(), но я не уверен, как получить ссылку на контроллер из запроса spe c.

Как мне написать этот тест, чтобы избежать запаха кода / устаревших подходов к тестированию?

Ответы [ 2 ]

1 голос
/ 19 марта 2020

Вы должны быть в отпуске.

Я думаю, что правильный путь - избегать заглушки как можно больше в запросе c, привратнику нужен токен для авторизации, чтобы я мог сделайте что-то вроде:

describe 'Items', type: :request do
  describe 'GET /items' do
    let(:application) { FactoryBot.create :oauth_application }
    let(:user)        { FactoryBot.create :user }
    let(:token)       { FactoryBot.create :access_token, application: application, resource_owner_id: user.id }
    before do
      get '/items', access_token: token.token
      @parsed_body = JSON.parse(response.body)
    end

    it 'includes all of the items' do
      expect(@parsed_body).to include(item_1)
      expect(@parsed_body).to include(item_2)
    end
  end
end

Вот несколько примеров того, как эти фабрики могут выглядеть.

Наконец, хорошие SO точки!

1 голос
/ 19 марта 2020

не думал ли вы вообще не издеваться current_user?

, если вы напишете тестового помощника для входа в user до того, как ваш запрос spe c, current_user будет заполнен автоматически как если бы это был настоящий пользователь. Код будет выглядеть следующим образом:

before do
  sign_in user
  get '/items'
  @parsed_body = JSON.parse(response.body)
end

, если вы используете devise gem для аутентификации, у него есть хорошая вики-страница о том, что здесь .

Это подход также рекомендуется здесь @ dhh

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...