ShockwaveNN
ShockwaveNN

Reputation: 2268

Rspec cannot check logger info output

I have an non-rails ruby application, that uses logger to handle log output to stdout.
I want to add specs for checking that output and found two ways to implement this and seems both ways don't work.

So both ways are in this spec.rb file:

require 'rspec' 
require 'logger'

describe 'Logger' do   
  it 'expect to output' do
    expect { Logger.new(STDOUT).info('Hello') }.to output.to_stdout    
  end

  it 'expect to recieve' do
    expect(Logger.new(STDOUT).info('Hello')).to receive(:info)   
  end 
end

I have output to terminal with log messages, but both verification are failed

Upvotes: 6

Views: 2324

Answers (2)

jmanrubia
jmanrubia

Reputation: 1967

Replace STDOUT with $stdout. This works:

expect { Logger.new($stdout).info('Hello') }.to output.to_stdout

The reason is that Rspec internally modifies the global variable $stdout to capture its contents with an StringIO. When using the constant, this mechanism does not work because STDOUT keeps the original value of $stdout.

Notice that you will have a similar problem is you initialize the logger outside of the block. The logger object will store internally the original reference and it won't work:

logger = Logger.new($stdout)
expect { logger.info('Hello') }.to output.to_stdout # This won't work

As per the second question:

expect(Logger.new(STDOUT).info('Hello')).to receive(:info)   

This is just a wrong usage of Rspec. It should be something like:

logger = Logger.new(STDOUT)
expect(logger).to receive(:info)   
logger.info("Hello")

Upvotes: 5

Anthony
Anthony

Reputation: 15977

I typically just use doubles like this:

describe 'logging' do
  it 'handles output' do
    logger = double('logger')
    allow(Logger).to receive(:new).and_return(logger)

    run_some_code
    expect(logger).to receive(:info).with("Hello")
  end
end

Upvotes: 2

Related Questions