Как проверить, что класс вызывается в методе контроллера с RSpec - PullRequest
0 голосов
/ 20 января 2019

Я тестирую свой контроллер, чтобы убедиться, что вызывается класс библиотеки и что функциональность работает так, как ожидалось. NB : Возможно, об этом спрашивали где-то еще, но мне нужна помощь с моей конкретной проблемой. Мне также хотелось бы узнать, как лучше всего это проверить.

Чтобы лучше объяснить мою проблему, я предоставлю контекст через код. У меня в папке /Lib есть класс, который генерирует события (не против, если вы не понимаете, что это значит). Класс выглядит примерно так:

class ChangeEmitter < Emitter
  def initialize(user, role, ...)
    @role = role
    @user = user
    ...
  end

  def emit(type)
    case type
    when CREATE
      payload = "some payload"
    when UPDATE
      payload = "some payload"
    ...
    end

    send_event(payload, current_user, ...)
  end
end

Вот как я использую его в моем контроллере:

class UsersController < ApplicationController

  def create
    @user = User.new(user_params[:user])
    if @user.save
      render :json => {:success => true, ...}
    else
      render :json => {:success => false, ...}
    end
    ChangeEmitter.new(@user, @user.role, ...).emit(ENUMS::CREATE)
  end
end

Извините, если какой-то код не имеет смысла, я пытаюсь объяснить проблему, не раскрывая слишком много кода.

Вот что я попробовал для своих тестов:

describe UsersController do
  before { set_up_authentication }

  describe 'POST #create' do
    it "calls the emitter" do
      user_params = FactoryGirl.attributes_for(:user)
      post :create, user: user_params

      expect(response.status).to eq(200)
      // Here is the test for the emitter
      expect(ChangeEmitter).to receive(:new)
    end
  end
end

Я ожидаю, что класс ChangeEmitter получит new, поскольку он вызывается сразу после выполнения действия create.

Вместо этого я получаю сообщение об ошибке:

(ChangeEmitter (class)).new(*(any args))
       expected: 1 time with any arguments
       received: 0 times with any arguments

Чего мне не хватает в приведенном выше коде и почему класс не получает новый. Есть ли лучший способ проверить вышеуказанную функциональность? Обратите внимание, что это Rspec. Ваша помощь будет высоко ценится. Спасибо.

1 Ответ

0 голосов
/ 20 января 2019

Вы должны поставить свой код expect(ChangeEmitter).to receive(:new) над почтовым запросом.Когда вы ожидаете, что класс получит метод, ваше выражение «ожидаемо» перед вызовом контроллера.Ожидается, что что-то случится в будущем.Итак, ваш тест должен выглядеть примерно так:

it "calls the emitter" do    
  user_params = FactoryGirl.attributes_for(:user)

  expect(ChangeEmitter).to receive(:new)

  post :create, user: user_params

  expect(response.status).to eq(200)
end

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

Заметив, что вы связываете действие "emit" после вызова "new", я понял, что янеобходимо обновить мой ответ для вашего конкретного случая использования.Вам нужно вернуть объект (я обычно возвращаю шпиона или двойника), который может вызвать emit.Для получения дополнительной информации о разнице между шпионами и двойниками посмотрите: https://www.ombulabs.com/blog/rspec/ruby/spy-vs-double-vs-instance-double.html

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

Итак, вы хотите сделать это следующим образом:

it "calls the emitter" do    

  user_params = FactoryGirl.attributes_for(:user)

  emitter = spy(ChangeEmitter)
  expect(ChangeEmitter).to receive(:new).and_return(emitter)

  post :create, user: user_params

  expect(response.status).to eq(200)
end
...