Knowing when to except
and when to allow
in an RSpec test is important. When you don’t care about the method being called, use allow
. When you do care, use expect
.
For instance, I was working on some code that:
The code essentially looked like:
expect(Logger).to receive(:log)
foo = Foo.new
expect(Logger).to receive(:log).with("Foo complete")
foo.do_stuff
This worked great, except it was flaky. Sometimes do_stuff
would log multiple times before the one our test cared about. This meant the 2nd expect did not get the right value and the test would sometimes fail. This solution to this was simple, use allow:
allow(Logger).to receive(:log)
foo = Foo.new
expect(Logger).to receive(:log).with("Foo complete")
foo.do_stuff
This change means Logger.log
can be called any number of times, but it must be called once with “Foo complete”. No more flaking test.