-
Notifications
You must be signed in to change notification settings - Fork 142
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
Multiple stubbings with argThat causes unexpected behavior #180
Comments
This is a good point, and well-argued. Would you be interested in trying to tackle a solution to this as a PR? If not, I'll try to get this prioritized |
I'm not sure if I feel comfortable contributing at this time, but I'll certainly take a look and see if I can do it myself or at least highlight some leads on potential fixes. Do you have any initial thoughts as to how to best solve this? I'm not as familiar with the rehearsal invocation logic to know what kind of things one might do to prevent this invocation... Is there perhaps a method with which the |
Thinking a moment longer, yes, we need to decide what a solution even looks like in this case before implementing something. I'm honestly a little bit stuck on what can be done here from td's perspective. Stubbings necessarily happen synchronously, so a return value needs to be resolved immediately. td.js also is not a "modal" library in that there's not a "rehearsal mode" and an "ok all my stubbings are in place now" mode to differentiate whether to evaluate an invocation to a return value. That means any rehearsal invocations need to act on the stubbings that came before them. The more I think about this, the more it feels intractable from the library's perspective. My advice would be to make your Here's an idea: write a custom matcher that's just like |
If you can think of a good matcher name for |
Wouldn't that matcher result in an incorrect state for the double, which would manifest as unexpected behavior in tests that might assert on double state like the number of invocations, or My initial thought was seeing if it might be possible to somehow mark rehearsal invocations that occur within I'm trying to grok the |
Let's focus on the first statement:
Why would this be? If an argThat predicate throws an error, calling that "not a match" seems reasonable to me in this case. Struggling to understand your point, but i don't doubt you. Maybe try this for yourself to experiment with something like this (written in browser/untested): var argWhich = td.matchers.create({
name: 'argWhich',
matches: function(matcherArgs, actual) {
var predicate;
predicate = matcherArgs[0];
try {
return predicate(actual);
} catch (e) {
return false;
}
}
}) |
I think my comment was erroneous based on a naive understanding of how td worked. That does work, but feels a bit sketchy especially as actual errors in the predicate will be difficult to debug. I also can't think of a good name for something like this. |
Well, it's why I wouldn't replace Other options:
|
That's fair; this isn't exactly something I'd expect anyone to see when stubbing directly in a test. My usecase was for creating slightly more robust fakes that could be reused in a few tests, reducing some duplication of stubbing and potential for errors between those duplicated stubs. An additional motivation for this was that with promise returning functions being stubbed with a specific expectation, a failed invocation can lead to an ambiguous error of |
Sure. The only guidance I'd give you is that more robust fakes require more robust edge-case handling, which can be particularly fraught unless you test the fakes themselves. In a sense, the library is intended to be terse and expressive to decrease the number of times where a fancier regime of fakes seems preferable. 2¢ |
You're not wrong; that's a fair stance to have. I wasn't necessarily sold on doing it that way, but playing around with it lead me to this problem. Still, it seems to me that this is a small wart on an otherwise unmatched api that would improve flexibility, even if not the default recommended usage pattern. It doesn't seem like an easy problem to solve without altering the interface, and if it's not I suppose I'll live without it, but if there was any way that we could potentially affect this without creating a whole new set of gotchas I think it would be great. I think I'll continue perusing the source and pondering if there's any way we could potentially do this. Certainly looks like a long shot at this point, but I'm willing to poke around and see regardless. Do you think this gotcha might be worth adding warnings for on the docs page for |
I would be open to warning people of two things on the stubbing doc page along the lines of:
|
Seems like a reasonable description to me 👍 |
Rehearsal invocations cause
argThat
matchers to be invoked, and can cause unexpected exceptions.Example: This code...
When run, will throw the exception:
Originating from line 3 of the snippet above. The rehearsal invocation of foo to set a new stubbing causes the invocation of the existing
argThat
matcher, which receives the td matcher instance (td.matchers.anything()
) asarg
, which of course does not have the propertyfoo
, and causes the exception above.This particular example can be fixed by ordering the argThat stubbing last, but scenarios where multiple argThat stubbings are required seem to have no current solution.
The text was updated successfully, but these errors were encountered: