In RSpec (specifically rspec-mocks), what is the difference between Message Expectations and Test Spies? They seem similar, and appear right next to each other as seperate sections in the readme.
i.e. what is the difference between:
expect(validator).to receive(:validate) # message expectation
and
expect(validator).to have_received(:validate) # test spy
Spies are an alternate type of test double that support this. pattern by allowing you to expect that a message has been received after the fact, using. have_received . You can use any test double (or partial double) as a spy, but the double must be setup to. spy on the messages you care about.
What is a mock in RSpec? (Or a mock in general, because this isn't a concept unique to RSpec.) A mock is an object used for testing. You use mocks to test the interaction between two objects. Instead of testing the output value, like in a regular expectation.
RSpec features doubles that can be used as 'stand-ins' to mock an object that's being used by another object. Doubles are useful when testing the behaviour and interaction between objects when we don't want to call the real objects - something that can take time and often has dependencies we're not concerned with.
Use let to define a memoized helper method. The value will be cached. across multiple calls in the same example but not across examples. Note that let is lazy-evaluated: it is not evaluated until the first time. the method it defines is invoked.
Message expectations can be set on any object and represent a declaration that something is going to happen (or not happen) to that object in the future. If the expectation is violated during subsequent test execution, the test will fail at the time the violation occurs. If the expectation has not been met by the end of the test, the test will fail as well.
The have_received
family of methods only works on test doubles and examines what has happened to the double in the past, from the time of the double's creation up through the current method call. It succeeds or fails at that point in time. The term "test spy" is a little misleading, because the support for this backward-looking mechanism is a standard part of rspec-mocks at this point. You don't do anything "special" to create a "test spy".
You can't always use spies when you test, basically for expectations on classes.
Example:
expect(User).to receive(:new)
there is no way to do this with a spy (unless you do dependency injection).
Now, you could do the following:
user = double('user', save: true)
expect(User).to receive(:new).and_return user
User.new.save
expect(user).to have_received(:save)
You see clearly that:
you have to set expectations on real object before you run the real code (it kind of looks weird to set expectations before triggering the code)
you can set expectation on spies after the real code, which is more natural
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With