mehowte
mehowte

Reputation: 449

How to mock method with expectation on what is passed to the block

Lets say we have a class:

class ObjectWithCaching
  def cached_attribute(key, cache_handler)
    cache_handler.cache(key) { expensive_operation }
  end

  def expensive_operation
    #...
  end
end

And we already tested cache_handler so we know that it will execute the block only when key is not found in cache.

We want to test if cache_handler#cache is executed properly.

Question is: How to write remaining pending spec?

describe ObjectWithCaching, "#cached_attribute" do
  let(:key) { double }
  let(:cache_handler) { double }

  specify do
    cache_handler.should_receive(:cache).with(key)
    subject.cached_attribute(key, cache_handler)
  end

  it "passes #expensive_operation to block of cache_handler#cache" do
    pending
    subject.cached_attribute(key, cache_handler)
  end
end

Upvotes: 0

Views: 133

Answers (1)

trptcolin
trptcolin

Reputation: 2340

Here's what I'd do. It feels kind of dirty to be mocking out another method on the same object (might expensive_operation belong on another class?), but given the constraints, I think this is the way to go. It'd sure be nice to be able to pass functions around directly and just check for function equality like you can in Clojure :)

it "passes #expensive_operation to block of cache_handler#cache" do
  cache_handler.stub!(:cache) do |k, block|
    subject.should_receive(:expensive_operation)
    block.call
  end 

  subject.cached_attribute(key, cache_handler)
end

Upvotes: 2

Related Questions