CapnKernul asks:
Hey Avdi. How would you test that a method’s provided block is called in RSpec? Would you stub #to_proc (for &block) and mock #call?
Typically the way I test that a block is called goes something like this:
describe ZeroWing do
let(:probe) { lambda{} }
context "given a signal handler" do
subject.on_we_get_signal(&probe)
it "triggers the handler when signaled" do
probe.should_receive(:call)
subject.we_get_signal!
end
end
end
That’s for the simple case of just checking if the block is called. When I want to make assertions about the block arguments, I often switch to a style which records the yielded arguments and then makes assertions on them after the fact.
describe Array do
subject { [1,2,3] }
describe "#reverse_each" do
it "yields the elements in backwards order" do
yielded = []
subject.reverse_each do |e| yielded << e end
yielded.should eq([3,2,1])
end
end
end
I don’t know if this is the best way, but it’s the way I usually do it.

I think
subject.on_we_get_signal(&probe)needs to be in abefore(:each)block–you can’t call it like that ddirectly in the “class body” of the example group.The mocking approach you’ve described here is interesting, I always use something closer to your second approach even for the simple case of just asserting the block was called:
it ‘calls the given block’ do
block_called = false
subject.method_that_calls_block { block_called = true }
block_called.should be_true
end
The mocking doesn’t gain anything over this approach IMHO, and it’s more fragile. If the method-under-test calls the block using #call, it’ll work fine, but what if it just uses a plain old
yield?+1 for
block_called = trueWhat about something like
MockBlockhere: https://gist.github.com/1428875That doesn’t care whether the implementation actually uses
#calloryield, and shows a readable technique for testing the order of the calls. I find that a lot nicer to read than the oldblock_called.should be_trueoryielded.should ==style.Nice!
Given the following code block:
barcode = Barby::Code128B.new(data)
File.open(“test.png”, ‘w’) do |f|
f.write barcode.to_png(height: 100, margin: 5)
end
How would I test that code within the block was executed? Specifically the calls to f.write or barcode.to_png?
You’d check to see if a file had been written to the filesystem!
Couldn’t you stub File.open to yield a mock file, then assert that the mock receives the write call?
The first rule of mocking is: Only mock what you own!
See http://www.virtuouscode.com/2013/04/22/rubytapas-freebie-the-end-of-mocking/ for more on why mocking out the filesystem is a bad idea.
The first example is just great! I really don’t like creating superfluous instance variables to validate things. By adding on a .with(foo) I can keep my tests completely out of the caller/consumer space. Thanks!