Opinionated mocking library for Python
Project description
Decoy is a mocking library designed for effective and productive test-driven development in Python. If you want to use tests to guide the structure of your code, Decoy might be for you!
Decoy mocks are async/await and type-checking friendly. Decoy is heavily inspired by (and/or stolen from) the excellent testdouble.js and Mockito projects. The Decoy API is powerful, easy to read, and strives to help you make good decisions about your code.
Install
# pip
pip install decoy
# poetry
poetry add --dev decoy
# pipenv
pipenv install --dev decoy
Setup
Pytest setup
Decoy ships with its own pytest plugin, so once Decoy is installed, you're ready to start using it via its pytest fixture, called decoy
.
# test_my_thing.py
from decoy import Decoy
def test_my_thing_works(decoy: Decoy) -> None:
...
Mypy setup
By default, Decoy is compatible with Python typing and type-checkers like mypy. However, stubbing functions that return None
can trigger a type checking error during correct usage of the Decoy API. To suppress these errors, add Decoy's plugin to your mypy configuration.
# mypy.ini
plugins = decoy.mypy
Other testing libraries
Decoy works well with pytest, 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 of
Decoy()
before each test - Call
decoy.reset()
after each test
For example, using the built-in unittest framework, you would use the setUp
fixture method to do self.decoy = Decoy()
and the tearDown
method to call self.decoy.reset()
. For a working example, see tests/test_unittest.py
.
Basic Usage
This basic example assumes you are using pytest. For more detailed documentation, see Decoy's usage guide and API reference.
Decoy will add a decoy
fixture to pytest that provides its mock creation API.
from decoy import Decoy
def test_something(decoy: Decoy) -> None:
...
!!! note
Importing 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 mock
Use decoy.mock
to create a mock based on some specification. From there, inject the mock into your test subject.
def test_add_todo(decoy: Decoy) -> None:
todo_store = decoy.mock(cls=TodoStore)
subject = TodoAPI(store=todo_store)
...
See creating mocks for more details.
Stub a behavior
Use decoy.when
to configure your mock's behaviors. For example, you can set the mock to return a certain value when called in a certain way using then_return
:
def test_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")
assert result == TodoItem(id="abc123", name="Write a test for adding a todo")
See stubbing with when for more details.
Verify a call
Use decoy.verify
to 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.
def test_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)
See spying with verify for more details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file decoy-2.1.1.tar.gz
.
File metadata
- Download URL: decoy-2.1.1.tar.gz
- Upload date:
- Size: 23.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.7.0 CPython/3.12.0 Linux/6.2.0-1015-azure
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 575bdbe81afb4c152cd99a34568a9aa4369461f79d6172c678279c5d5585befe |
|
MD5 | 2c5cb713e91a526c18b9bfdf9ba89ca5 |
|
BLAKE2b-256 | 541d9d5bb8307556802ddee07189177d6d21c116645d6b79841a8bfc32f68a62 |
File details
Details for the file decoy-2.1.1-py3-none-any.whl
.
File metadata
- Download URL: decoy-2.1.1-py3-none-any.whl
- Upload date:
- Size: 28.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.7.0 CPython/3.12.0 Linux/6.2.0-1015-azure
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 7ddcc08b8ce991f7705cee76fae9061dcb17352e0a1ca2d9a0d4a0306ebd51cd |
|
MD5 | 9ddc41bc8e9ae6ce5a8aafc7c4231e95 |
|
BLAKE2b-256 | a2841a324d1cfebd8b23d29df95239e2a276b902a32b3127f3a62638b8eae3f5 |