Starkers
Starkers

Reputation: 10541

Mock specific instance

Here's the trivial code I'm testing:

def inside
    @location = Location.find(params[:id])
    @locations = @location.inside
end

And here's the expectation:

describe '#inside' do
    # objects
    let(:location){            FactoryGirl.create(:location, longitude: 5, latitude: 5, radius: 5) }
    let(:location_inside){     FactoryGirl.create(:location, longitude: 6, latitude: 5, radius: 1) }
    let(:location_not_inside){ FactoryGirl.create(:location, longitude: 10, latitude: 10, radius: 1) }

    # request
    let(:request){ get :inside, id: location.id }

    describe 'response' do
        before do
            location.should_receive(:inside).and_return([location_inside])
            request
        end

        specify{ expect( assigns :location).to eq location }

        specify{ expect( assigns :locations).to include location_inside }
        specify{ expect( assigns :locations).to_not include location_not_inside }
        specify{ expect( assigns :locations).to_not include location } # a bug I was getting
    end
end

It passes perfectly if I'm not mocking the location instance. However, I want to mock but I can't because this happens:

Failure/Error: airspace_one.should_receive(:inside).and_return([location_inside])
       (#<Location:0x0000000325ddb8>).inside(any args)
           expected: 1 time with any arguments
           received: 0 times with any arguments

Now, it's obvious why this is happening. I think it's because the location created by FactoryGirl is an identical but seperate instance of Location. So how am I meant to mock the instance in my code base? I could use any_instance_of, but apparently that's a smell?

Upvotes: 0

Views: 46

Answers (1)

Peter Alfvin
Peter Alfvin

Reputation: 29389

If you want to test the behavior of your inside method, you can set an expectation on Location to return your instance, as in:

expect(Location).to receive(:find).with(location.id).and_return(location)

Upvotes: 1

Related Questions