Stubbing a method on controller instances on rspec type controller is easy, just:

allow(controller).to receive_messages(current_user: create(:user))

And on rspec type request is a common this bad practice

allow_any_instance_of(MyController).to receive(:current_user).and_return(create(:user))

A smart way to avoid this is use of allow_any_instance_of. Let's code this solution!

On spec/support/helpers/next_instance_of.rb code this:

module NextInstanceOf
  def expect_next_instance_of(klass, *new_args, &block)
    stub_new(expect(klass), *new_args, &block)
  end

  def allow_next_instance_of(klass, *new_args, &block)
    stub_new(allow(klass), *new_args, &block)
  end

  private

  def stub_new(target, *new_args, &block)
    receive_new = receive(:new)
    receive_new.with(*new_args) if new_args.any?

    target.to receive_new.and_wrap_original do |method, *original_args|
      method.call(*original_args).tap(&block)
    end
  end
end

On spec/spec_helper.rb include this file and include on config.

require_relative './support/helpers/next_instance_of'

#...

RSpec.configure do |config|
  config.include NextInstanceOf

  #...

end

#...

Now we really can avoid allow_any_instance_of using allow_next_instance_of just:

allow_next_instance_of(described_class) do |my_controller|
  allow(my_controller).to receive(:current_user).and_return(create(:user, admin: true))
end

Something was missing?


🗓 2020-09-14
194 👀