This one had Adam and me stumped for a while. Trying to check that a method is only called on objects that respond to it:
describe "Foo#call_all_the_things" do let(:foo_1) { stub :foo_1, bar: "hello" } let(:foo_2) { stub :foo_2 } subject { Foo.new foo_1, foo_2 } it "only calls bar on objects that respond to it" do foo_1.should_receive :bar foo_2.should_not_receive :bar subject.call_all_the_things(:bar) end end class Foo def initialize *things @things = things end def call_all_the_things method @things.each do |thing| thing.send method if thing.respond_to? method end end end 1) Foo#call_all_the_things only calls bar on objects that respond to it Failure/Error: thing.send method if thing.respond_to? method (Stub :foo_2).bar(no args) expected: 0 times received: 1 time
Hmm. Why is it calling bar
on the thing that doesn’t respond to it? Perhaps rSpec doubles don’t handle respond_to?
properly?
[1] pry(main)> require "rspec/mocks/standalone" => true [2] pry(main)> foo = stub foo: 123 => #<:mocks::mock:0x3fd07d246f34> [3] pry(main)> foo.respond_to? :foo => true [4] pry(main)> foo.respond_to? :bar => false
Nope.
FX: lightbulb above head
Of course! To do the should_not_receive
check, it needs to stub the method, which means it responds to it!
Two possible solutions: either let the fact that the missing method isn’t called be tested implicitly, or specify that when objects that don’t respond to the method exist, no NoMethodError
is raised.