-
Notifications
You must be signed in to change notification settings - Fork 4
Description
If you have production code that looks like this:
with foo.bar(bar_arg) as baz:
...
Then its Decoy test might do:
bar_arg_captor = matchers.Captor()
decoy.when(foo.bar(bar_arg_captor())).then_enter_with("baz value")
But sometimes the with
statement has no as
clause:
with foo.bar(bar_arg):
...
I expected this to work:
bar_arg_captor = matchers.Captor()
decoy.when(foo.bar(bar_arg_captor())).then_enter_with(None)
But this causes the production code's call to foo.bar(bar_arg)
to return None
. It should instead return a context manager that returns None
when it's entered.
It looks to me like this is an unintentional side-effect of the way StubBehavior
works internally:
Lines 7 to 14 in c23d145
class StubBehavior(NamedTuple): | |
"""A recorded stub behavior.""" | |
return_value: Optional[Any] = None | |
context_value: Optional[Any] = None | |
error: Optional[Exception] = None | |
action: Optional[Callable[..., Any]] = None | |
once: bool = False |
It can't distinguish between being configured with a context_value
that's None
versus not being configured with a context_value
at all.
To solve a similar problem, the implementation of dataclasses
uses a special MISSING
sentinel value that's distinct from None
. Maybe a similar pattern could work here.