2

For example, it generated a log(my_work.log) content as:

I, [2015-05-14T00:00:00.000000 #5590]  INFO -- : Work started.

I want to test if my_work.log has content Work started., how to do?

I don't want to match all line include datetime, because that contains #5590, I can't stub it.

s-cho-m
  • 967
  • 2
  • 13
  • 28

3 Answers3

8

You can pass in an instance of StringIO when initializing Logger to capture the output and then match on the expected content:

require 'logger'

describe "log" do
  let(:log) { StringIO.new }
  let(:logger) { Logger.new(log) }
  let(:expected) { "Work started" }

  it "should add the expected content to the log" do
    logger.info(expected)
    log.rewind
    expect(log.read).to match(/.+#{expected}$/)
  end

end
zetetic
  • 47,184
  • 10
  • 111
  • 119
3

Rails.logger uses some methods to log things, for example:

  • debug
  • info
  • fatal
  • warn

So in your case you use info, to log something, instead loking for a match, you can detect if method info was called:

it 'logs exception' do
  # some code
  expect(Rails.logger).to receive(:info)
  # execute the line that logs something
end

Even you can add parameters to receive method with reserved word with:

expect(Rails.logger).to receive(:info).with('Work started.')

This cause you need to specify something

Check rspec and rails logger

Also check this stackoverflow post

Community
  • 1
  • 1
G. I. Joe
  • 1,585
  • 17
  • 21
3

With RSpec's output matcher (introduced in 3.0) you can do the following:

expect { my_method }.to output("my message").to_stdout
expect { my_method }.to output("my error").to_stderr

In case of libraries such as Logger or Logging you may have to use output.to_<stdout/stderr>_from_any_process.

It's simple, clean and will test whether your messages actually reach the output.

thisismydesign
  • 21,553
  • 9
  • 123
  • 126