I have an expensive method called calculate_total. I need a method called total that will return the result of calculate_total. Subsequent calls to total should return the previous result of calculate_total.
I want to do this in a test driven way. Here are my tests (I'm using RSpec):
describe Item do
  describe "total" do
    before do
      @item = Item.new
      @item.stub!(:calculate_total => 123)
    end
    it "returns the calculated total" do
      @item.total.should == 123
    end
    it "subsequent calls return the original result" do
      previous_total = @item.total
      @item.total.should equal(previous_total)
    end
  end
end
This is not a good test because the following method makes the tests pass, but I was expecting the second test to fail:
def total
  calculate_total
end
The reason is calculate_total returns a Fixnum so ruby doesn't see the result as 2 different objects. I was expecting the second test to fail, so then I could do the following to make it pass:
def total
  @total ||= calculate_total
end
Anyone know a better way to test this?
I don't think this is the best/correct way to test it, but I've settled on this: https://gist.github.com/1207270
I think your gist is fine: what you want to test is whether or not calculate_total is called more than once, and that's exactly what you're doing. The only difference I might suggest is a slightly more explicit test:
it "subsequent calls don't calculate the total, but still return the original result" do
  @item.should_receive(:calculate_total).once
  2.times do 
    @item.total.should == 123
  end
end
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With