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
_______________________________________________
rspec-users mailing list
rspec-users@rubyforge.org
http://rubyforge.org/mailman/listinfo/rspec-users

Reply via email to