[rspec-users] should_receive(:x).at_most/exactly... ignored when method is previously stubbed?

Lenny Marks lenny at aps.org
Tue Dec 1 11:46:07 EST 2009


I've always used the idiom of stub collaborations in a before block  
and then focus in specific examples with should_receive. (e.g.  
should_receive takes presence over stub). I was just attempting to  
write an example for caching behavior and ran into something counter- 
intuitive, at least IMHO.  See the following(contrived) example.

class ExpensiveOperation
    def self.lookup(question)
       "This goes to the database"
    end
end

class UsesExpensiveOperation
    def initialize
       @cache = {}
    end

    def answer_for(question)
       # oops, this is broken, it was supposed to be cached
       # @cache[question] ||= ExpensiveOperation.lookup(question)
       @cache[question] = ExpensiveOperation.lookup(question)
    end
end

describe "suprising behavior" do
    before do
       @object = UsesExpensiveOperation.new

       ExpensiveOperation.stub(:lookup).and_return('whatever')
    end

    it "should fail because I'm specifying that lookup should be  
called at most one time, but that's not true" do
        
ExpensiveOperation 
.should_receive(:lookup).at_most(:once).and_return('an answer')

       @object.answer_for("my question")
       @object.answer_for("my question")
    end

end

This seems dangerous to me. Assuming I hadn't initially stubbed in the  
before block and everything worked as expected, if someone later  
stubs :lookup in the before block because they are adding new examples  
that don't care about it, my explicit example becomes misleadingly  
useless.

Does this surprise anyone else?

-lenny


More information about the rspec-users mailing list