You may want to check how to use stubs and mocks with RSpec before diving in into this subject.
The only one syntax difference is the first method. With stubs you would use
allow while with mocks you would use
Stubs are used to avoid execution of other methods and make them return desired values. Mocks are used to check if given method was executed with desired arguments and frequency.
It’s always better to learn by the example so let’s use one. We will create class and sample test for it:
class Message def initialize(user: user) @user = user end def send user.update_message_sent_at name = user.name(format: 'message') Emailer.send_message(name) end private attr_reader :user end
We don’t really want to call any of those three methods so we will stub them and then use mocks to check if they were executed properly.
require 'spec_helper' describe Message do describe '#send' do it 'sends message' do user = instance_double(User) name = 'Tim' allow(user).to receive(:name).with(format: 'message').and_return(name) allow(user).to receive(:update_message_sent_at) alloW(Emailer).to receive(:send_message).with(name) message = Message.new(user: user) message.send expect(user).to have_received(:update_message_sent_at).once expect(user).to have_received(:name).with(format: 'message').once expect(Emailer).to have_received(:send_message).with(name).once end end end
And that’s it! As you can see we used
stubs to not execute original code and used
mocks to check if given method was really invoked. Such test structure is named as spies – I will explain it tomorrow.