Closed mcous closed 2 years ago
then_enter_with
is both pretty difficult to type and unnecessary with the addition of nullcontext
to contextlib. Might be better as a docs addition instead of a Stub
method to maintain
def test_enter_with_smoke_test(decoy: Decoy) -> None:
"""It should be able to stub out a context manager method."""
class _ContextManager:
def get_value(self) -> int:
raise NotImplementedError()
class _ContextParent:
@contextmanager
def get_context(self) -> Iterator[_ContextManager]:
raise NotImplementedError()
context_parent = decoy.mock(cls=_ContextParent)
context_manager = decoy.mock(cls=_ContextManager)
decoy.when(context_parent.get_context()).then_return(nullcontext(context_manager))
decoy.when(context_manager.get_value()).then_return(42)
with context_parent.get_context() as subject:
result = subject.get_value()
assert result == 42
Still to research: __enter__
and __exit__
behavior of spies
Currently, the Spy
class is incompatible with usage as a ContextManager (i.e. it'll fail out if you try to decoy.when(xyz.__enter__())
). It looks like there's a path forward involving defining __enter__
and __exit__
methods on Spy
and leaning on typechecking (rather than runtime checking) to alert the user if usage of with
is improper in a given test
Overview
In Python, context managers present a useful and reliable API for performing actions that require cleanup. Often, the right tool for a given job is a context manager.
Decoy doesn't provide a good interface for mocking out a dependency that is a context manager. Sine Decoy's job is to help you design your internal APIs, it should ideally let you shake our a dependency that works best as a context manager.
Ideas and brainstorming
then_enter_with
stub method might be interesting, especially for methods that use the context manager decoratorSpy
do anything special with the__enter__
and__exit__
magic methods?