RSpec’s spies are a cool thing for testing a message was received after invoking certain method. Like for example to make sure our Service that implements Wisper is always subscribing to certain listener.
Also, if you’re not familiar with Wisper, make sure to check it out, is a cool way to implement Publish-Subscribe capabilities, really awesome.
Anyways, let’s assume we want to test the create method in our controller, and its implementation is something like this:
def create
service = MyCustomService.new(params)
service.subscribe(MySubscriber.new)
# I do whatever I have to do in after this
end
In create we want to make sure our service always subscribes to MySubscriber
. How do we test this?
describe 'Service is subscribing to' do
context 'MySubscriber' do
let!(:service_double) {
service_double = double('service')
allow(service_double).to receive(:subscribe)
allow(MyCustomService.new).to receive(:new).and_return(service_double)
service_double
}
let!(:subscriber_double) {
subscriber_double = instance_double(MySubscriber)
allow(MySubscriber).to receive(:new).and_return(subscriber_double)
subscriber_double
}
it 'on create' do
my_model = FactoryGirl.build(:my_model)
post :create, model: my_model.attributes
expect(service_double).to have_received(:subscribe).with(subscriber_double)
end
end
end
What the above spec means is the following:
let!(service_double)
: We create a double ofMyCustomService
, we mocksubscribe
to allow spying on it and we make sure thenew
method in our service class always returns this double.let!(:subscriber_double)
: We create in instance double and similar to ourMyCustomService
mocking, we mockMySubscriber#new
to return this double. The idea is that we can confirm the subscribe was called with this particular instance.- Finally
expect(service_double).to have_received(:subscribe).with(subscriber_double)
: This is what closes the deal in our test, we are basically saying: my mocked service called subscribe and it actually included my mocked subscriber AKA my create is subscribing to my listener.
Pretty cool stuff to enforce certain requirements in specific methods.