Package: decoy
DecoyOpinionated mocking library for PythonUsage guide and documentationDecoy is a mocking library designed foreffective and productive test-driven developmentin Python. If you want to use tests to guide the structure of your code, Decoy might be for you!Decoy mocks areasync/awaitandtype-checkingfriendly. Decoy is heavily inspired by (and/or stolen from) the excellenttestdouble.jsandMockitoprojects. The Decoy API is powerful, easy to read, and strives to help you make good decisions about your code.Install# pippipinstalldecoy# poetrypoetryadd--devdecoy# pipenvpipenvinstall--devdecoySetupPytest setupDecoy ships with its ownpytestplugin, so once Decoy is installed, you're ready to start using it via its pytest fixture, calleddecoy.# test_my_thing.pyfromdecoyimportDecoydeftest_my_thing_works(decoy:Decoy)->None:...Mypy setupBy default, Decoy is compatible with Pythontypingand type-checkers likemypy. However, stubbing functions that returnNonecan trigger atype checking errorduring correct usage of the Decoy API. To suppress these errors, add Decoy's plugin to your mypy configuration.# mypy.iniplugins=decoy.mypyOther testing librariesDecoy works well withpytest, but if you use another testing library or framework, you can still use Decoy! You just need to do two things:Create a new instance ofDecoy()before each testCalldecoy.reset()after each testFor example, using the built-inunittestframework, you would use thesetUpfixture method to doself.decoy = Decoy()and thetearDownmethod to callself.decoy.reset(). For a working example, seetests/test_unittest.py.Basic UsageThis basic example assumes you are usingpytest. For more detailed documentation, see Decoy'susage guideandAPI reference.Decoy will add adecoyfixture to pytest that provides its mock creation API.fromdecoyimportDecoydeftest_something(decoy:Decoy)->None:...!!! noteImporting the `Decoy` interface for type annotations is recommended, but optional. If your project does not use type annotations, you can simply write:

```python
def test_something(decoy):
    ...
```Create a mockUsedecoy.mockto create a mock based on some specification. From there, inject the mock into your test subject.deftest_add_todo(decoy:Decoy)->None:todo_store=decoy.mock(cls=TodoStore)subject=TodoAPI(store=todo_store)...Seecreating mocksfor more details.Stub a behaviorUsedecoy.whento configure your mock's behaviors. For example, you can set the mock to return a certain value when called in a certain way usingthen_return:deftest_add_todo(decoy:Decoy)->None:"""Adding a todo should create a TodoItem in the TodoStore."""todo_store=decoy.mock(cls=TodoStore)subject=TodoAPI(store=todo_store)decoy.when(todo_store.add(name="Write a test for adding a todo")).then_return(TodoItem(id="abc123",name="Write a test for adding a todo"))result=subject.add("Write a test for adding a todo")assertresult==TodoItem(id="abc123",name="Write a test for adding a todo")Seestubbing with whenfor more details.Verify a callUsedecoy.verifyto assert that a mock was called in a certain way. This is best used with dependencies that are being used for their side-effects and don't return a useful value.deftest_remove_todo(decoy:Decoy)->None:"""Removing a todo should remove the item from the TodoStore."""todo_store=decoy.mock(cls=TodoStore)subject=TodoAPI(store=todo_store)subject.remove("abc123")decoy.verify(todo_store.remove(id="abc123"),times=1)Seespying with verifyfor more details.