Testing memoization

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 test mode. Here are my tests (I use 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 skips the tests, but I expected the second test to fail:

 def total calculate_total end 

The reason calculate_total returns a Fixnum , so ruby ​​does not see the result as 2 different objects. I was expecting the second test to fail, so I could do the following to pass:

 def total @total ||= calculate_total end 

Does anyone know a better way to test this?

I don't think this is the best / correct way to test it, but I decided: https://gist.github.com/1207270

+6
source share
2 answers

I think your point is fine: what you want to check is that calc_total is called more than once, and that is exactly what you are doing. The only difference I could 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 
+6
source

You can call it twice in the same specification and compare the returned objects to make sure they are equal:

 it "should memoize it" do total = Item.total # second call will yield a different object if not memoized Item.total.should == total end 
-1
source

Source: https://habr.com/ru/post/897012/


All Articles