Reputation: 3130
This question tells me how to test logger statements from RSpec model and controller specs. Unfortunately, it doesn't seem to work from a feature spec. With this code:
# controller.rb
def action
logger.info 'foobar'
end
# spec.rb
scenario 'logging should work' do
expect(Rails.logger).to receive(:info).with('foobar')
visit action_path
end
I get the error:
Failure/Error: visit action_path
#<ActiveSupport::Logger:0x007ff45b6e5ad0> received :info with unexpected arguments
expected: ("foobar")
got: (no args)
The test.log
file does not contain foobar
, so it seems the test is failing immediately, before the controller action has a chance to complete.
Is there some way to use this expect(Rails.logger)
syntax in a feature spec?
Upvotes: 3
Views: 2642
Reputation: 2351
The Rails.logger.info method can take a string or a block. If you're invoking the block form then it will give this "got: (no args)" output.
For example
logger.info 'foobar'
...all on one line will call .info with a string, but if you do
logger.info
"foobar foobar longer message so I'll put it on its own line"
split across two lines without brackets, then you're actually passing a block. Add some brackets...
logger.info(
"foobar foobar longer message so I'll put it on its own line"
)
...and you're back to a string.
He says knowingly after bashing his head on this problem for a few hours :-)
Before realising that, I started figuring out how to mock the Rails.logger class. That might be a useful approach for you or others. Maybe you're calling with a block for some other reason (something to do with feature vs controller specs?), or maybe you can't change the calling code, in which case... something like this might be a useful starting point:
class LoggerMock < Object
def initialize; end
def info(progname = nil, &block)
mock_info(block.call)
end
end
and
logger_mock = LoggerMock.new
allow(Rails).to receive(:logger).and_return(logger_mock)
expect(logger_mock).to receive(:mock_info).with('foobar')
Upvotes: 2