moduleCallCounterdefcount_calls_to(method_name)
original_method =instance_method(method_name)
unlessclass_variable_defined?(:@@call_counter):
class_variable_set(:@@call_counter, {})
end
call_counter =class_variable_get(:@@call_counter)
define_method(method_name) do |*args|
call_counter[method_name] ||=0
call_counter[method_name] +=1
bound_original_method = original_method.bind(self)
bound_original_method.call(*args)
end
metaclass =class<<self; self; end
metaclass.instance_evaldodefine_method(:calls_to) do |m|
call_counter[m].nil??0 : call_counter[m]
enddefine_method(:reset_counters) do
call_counter.each_keydo |k|
call_counter[k] =0endendendendend
call_foo.rb
require"call_counter"classCallFooextendCallCounterdeffoo; "foo"; enddefbar; "bar"; end
count_calls_to :foo
count_calls_to :barend
call_counter_spec.rb
require"call_foo"require"spec"
describe CallFoodobefore(:each) do@call_foo=CallFoo.newCallFoo.reset_countersend
it "should have a method calls_to"doCallFoo.shouldrespond_to(:calls_to)
end
it "method counter should be zero at start"doCallFoo.calls_to(:foo).should==0end
it "should reset counters"do4.times {@call_foo. foo }
CallFoo.reset_countersCallFoo.calls_to(:foo).should==0end
it "should count the number of times a counted method has been called"do4.times {@call_foo.foo }
CallFoo.calls_to(:foo).should==4end
it "should be able to count several methods' calls"do4.times {@call_foo.foo }
CallFoo.calls_to(:foo).should==47.times {@call_foo.bar }
CallFoo.calls_to(:bar).should==7end
it "shold count bar calls correctly, too"do7.times {@call_foo.bar }
CallFoo.calls_to(:bar).should==7endend