Infinite loop when used on objects that define `==`
adam12 opened this issue · comments
Adam Daniels commented
I only briefly dug into the cause, but wasn't able to find it. Posting a repro here in case anybody else cares to look.
require "mocktail"
class Foobar < Sequel::Model
def name
"Bar"
end
end
foobar = Mocktail.of(Foobar)
Mocktail.stubs { foobar.name }.with { "Foobar" }
Mocktail.explain(foobar)
Run with sequel mock://sqlite <file.rb>
Output
I, [2021-11-15T02:43:07.555625 #52542] INFO -- : (0.000001s) SELECT * FROM `foobars` LIMIT 0
/usr/local/bundle/gems/mocktail-0.0.6/lib/mocktail/share/determines_matching_calls.rb:4:in `determine': stack level too deep (SystemStackError)
from /usr/local/bundle/gems/mocktail-0.0.6/lib/mocktail/handles_dry_call/fulfills_stubbing/finds_satisfaction.rb:11:in `block in find'
from /usr/local/bundle/gems/mocktail-0.0.6/lib/mocktail/handles_dry_call/fulfills_stubbing/finds_satisfaction.rb:10:in `each'
from /usr/local/bundle/gems/mocktail-0.0.6/lib/mocktail/handles_dry_call/fulfills_stubbing/finds_satisfaction.rb:10:in `find'
from /usr/local/bundle/gems/mocktail-0.0.6/lib/mocktail/handles_dry_call/fulfills_stubbing/finds_satisfaction.rb:10:in `find'
from /usr/local/bundle/gems/mocktail-0.0.6/lib/mocktail/handles_dry_call/fulfills_stubbing.rb:22:in `satisfaction'
from /usr/local/bundle/gems/mocktail-0.0.6/lib/mocktail/handles_dry_call/fulfills_stubbing.rb:12:in `fulfill'
from /usr/local/bundle/gems/mocktail-0.0.6/lib/mocktail/handles_dry_call.rb:16:in `handle'
from /usr/local/bundle/gems/mocktail-0.0.6/lib/mocktail/imitates_type/makes_double/declares_dry_class.rb:45:in `block (2 levels) in define_double_methods!'
... 9981 levels...
from /usr/local/bundle/gems/sequel-5.50.0/bin/sequel:260:in `each'
from /usr/local/bundle/gems/sequel-5.50.0/bin/sequel:260:in `<top (required)>'
from /usr/local/bundle/bin/sequel:23:in `load'
from /usr/local/bundle/bin/sequel:23:in `<main>'
Justin Searls commented
Thanks for raising this, Adam!
Adam Daniels commented
Happy Holidays!
I spent some more time looking at this. It's not necessarily a bug when used with Sequel, but with objects that define their own ==
method.
require "mocktail"
class Baz
def name
"Baz"
end
def ==(other)
end
end
foobar = Mocktail.of(Baz)
Mocktail.stubs { foobar.name }.with { "FoobarBaz" }
Mocktail.explain(foobar)
p foobar.name
Removing ==
from the list of double methods fixes this, and the tests still pass.
diff --git a/lib/mocktail/imitates_type/makes_double/declares_dry_class.rb b/lib/mocktail/imitates_type/makes_double/declares_dry_class.rb
index fb968a3..b9e3186 100644
--- a/lib/mocktail/imitates_type/makes_double/declares_dry_class.rb
+++ b/lib/mocktail/imitates_type/makes_double/declares_dry_class.rb
@@ -40,7 +40,7 @@ module Mocktail
def define_double_methods!(dry_class, type, instance_methods)
handles_dry_call = @handles_dry_call
- instance_methods.each do |method|
+ (instance_methods - [:==]).each do |method|
dry_class.define_method method, ->(*args, **kwargs, &block) {
handles_dry_call.handle(Call.new(
singleton: false,