user2490003
user2490003

Reputation: 11920

Mocking `Rails.logger` in the RSpec tests for my Gem

I'm writing a Ruby gem, and below is the implementation of how I create a new Logger.

My gem may or may not be used inside of Rails, so it tries to use Rails.logger IF one exists.

require 'logger'

module MyLoggeer
  def logger
    @logger ||= rails_logger || Logger.new($stdout)
  end

  def rails_logger
    if defined?(::Rails) && ::Rails.respond_to?(:logger) && !::Rails.logger.nil?
      ::Rails.logger
    else
      nil
    end
  end
end

My gem does not have Rails defined anywhere as a constant. If I wanted to test the above logic with RSpec, is there a way for me to -

  1. Define a mock Rails object
  2. Have it respond to a logger method?

I suppose I could define a dummy class inside my spec files, but I was hoping there was a way to easily mock / stub this out instead.

Thanks!

Upvotes: 0

Views: 612

Answers (1)

max
max

Reputation: 102443

With RSpec mocks you can use a double (as in stunt double) to create a stand in for any object.

You then use allow to allow the double to receive messages and expect to set method expectations.

let(:logger) do
  instance_double("Logger")
end

let(:rails) do
  double("Rails")
end

before do
  allow(rails).to receive(:logger).and_return(logger)
  stub_const("Rails", rails)
end

You can also use instance doubles and class doubles to create doubles of existing classes - this will verify that you only call methods that actually exist on the class you are doubling.

stub_const will stub the value of a constant for the duration of an example.

Upvotes: 3

Related Questions