Reputation: 2268
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
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
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