rspec-mocks' doubles are designed to only last for one example
rspec, rspec-mocks, ruby, ruby-on-rails, unit-testing
Solution
surely this is an appropriate use of a double being used in 2 examples.
No, it's not. :) You're trying to use a class variable; do not do that because the variable doesn't span examples. The solution is to set the client each time i.e. in each example.
Bad:
@client ||= Strava::Api::V3::Client.new(access_token: 'abc123')
Good:
@client = Strava::Api::V3::Client.new(access_token: 'abc123')
Problem
I've got a question about how to share rspec-mocks' double between examples. I'm writing a new rails app with rspec-mocks `3.1.3`. I'm used to using the old (< 2.14 and and trying to update my knowledge if current rspec usage. I have a model method: ``` def self.from_strava(activity_id, race_id, user) @client ||= Strava::Api::V3::Client.new(access_token: 'abc123') activity = @client.retrieve_an_activity(activity_id) result_details = {race_id: race_id, user: user} result_details[:duration] = activity['moving_time'] result_details[:date] = Date.parse(activity['start_date']) result_details[:comment] = activity['description'] result_details[:strava_url] = "http://www.strava.com/activities/#{activity_id}" Result.create!(result_details) end ``` And here is the spec: ``` describe ".from_strava" do let(:user) { FactoryGirl.build(:user) } let(:client) { double(:client) } let(:json_response) { JSON.parse(File.read('spec/support/strava_response.json')) } before(:each) do allow(Strava::Api::V3::Client).to receive(:new) { client } allow(client).to receive(:retrieve_an_activity) { json_response } allow(Result).to receive(:create!) end it "sets the duration" do expect(Result).to receive(:create!).with(hash_including(duration: 3635)) Result.from_strava('123', 456, user) end it "sets the date" do expect(Result).to receive(:create!).with(hash_including(date: Date.parse("2014-11-14"))) Result.from_strava('123', 456, user) end end ``` When I run a single test on it's own it's fine, but when I run the whole `describe ".from_strava"` block it fails with the message ``` Double :client was originally created in one example but has leaked into another example and can no longer be used. rspec-mocks' doubles are designed to only last for one example, and you need to create a new one in each example you wish to use it for. ``` I understand what it's saying, but surely this is an appropriate use of a `double` being used in 2 examples. After all, the `client` double isn't important to the example, it's just a way for me to load the canned response. I guess I could use WebMock but that seems very low-level and doesn't translate well to the actual code written. We should only be asserting one thing per example after all. I had thought about replacing the `client` double with a call to ``` allow(Strava::Api::V3::Client).to receive_message_chain(:new, :retrieve_an_activity) { json_response } ``` but that doesn't seem to be the right approach either, given that the documentation states that `receive_message_chain` should be a code smell. So if I shouldn't use `receive_message_chain`, shared `client` double and also follow the standard DRY principle then how should I fix this? I would love some feedback on this. Thanks, Dave