-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AmbiguousDemonstrationError when incorrectly using of_next vs replace and class has matching instance method #10
Comments
Ah, this is slightly thornier and worse than you might think. It's actually got nothing to do with singleton/instance method shadowing nor about the method being on the same. This script will fail in exactly the same way: class Steward
def retrieve_fighter_weapon
Fighter.new.weapon
end
end
class Fighter
def weapon
"sword"
end
end
Mocktail.of_next(Fighter)
steward = Steward.new
Mocktail.stubs { steward.retrieve_fighter_weapon }.with { nil } Here's what's happening:
Here's the state of the internal storage of fake calls during the run; it sees two calls just happened instead of one, which is what's triggering the cabinet.calls
=> [#<struct Mocktail::Call
singleton=true,
double=StubTest::Fighter,
original_type=StubTest::Fighter,
dry_type=StubTest::Fighter,
method=:new,
original_method=nil,
args=[],
kwargs={},
block=nil>,
#<struct Mocktail::Call
singleton=false,
double=#<Mocktail of StubTest::Fighter:0x0000000104730208>,
original_type=StubTest::Fighter,
dry_type=#<Class for mocktail of StubTest::Fighter:0x00000001047308e8>,
method=:weapon,
original_method=
#<UnboundMethod: StubTest::Fighter#weapon() /Users/justin/code/testdouble/mocktail/test/safe/stub_test.rb:453>,
args=[],
kwargs={},
block=nil>] I don't know what we can do to avoid this, short of using a Ruby parser to read the literal code string inside each demonstration block and then applying some additional intelligence/heuristics, but that'd probably double the complexity of the library and would always be defeated by method extraction and metaprogramming. |
I wonder if there’s a way to check that the mocked method is / is not called for the first time in the stubs block, and warn if it is. |
@calebhearth the tricky thing there is that for cases where the call is intended to be verified, it would be appropriate for it to not be called the first time in a stubs block, but rather by the subject. I think one thing we definitely could do is improve the error message to be way more clear about which failure mode they're seeing, splitting it up into "hey in this stubs call, we didn't detect any mock interactions and that's a bug" vs "hey in this verify you actually called two mocked methods, X and Y and that's a bug" |
Given a class which has matching instance and class methods, if a test incorrectly calls
Mocktail.of_next
instead ofMocktail.replace
then tries to demonstrate a call to the method, this error is raised:I'd expect there to be 0 invocations detected, but even better I'd love to be told that I'm not demonstrating using anything that's been mocked yet.
Here's a basic reproduction:
ambiguous.rb:
$ ruby ambiguous.rb
The text was updated successfully, but these errors were encountered: