Skip to main content

Opinionated mocking library for Python

Project description

Decoy logo

Decoy

Opinionated mocking library for Python

Usage guide and documentation

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:

  1. Create a new instance of Decoy() before each test
  2. 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

decoy-2.1.1.tar.gz (23.6 kB view details)

Uploaded Source

Built Distribution

decoy-2.1.1-py3-none-any.whl (28.1 kB view details)

Uploaded Python 3

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

Hashes for decoy-2.1.1.tar.gz
Algorithm Hash digest
SHA256 575bdbe81afb4c152cd99a34568a9aa4369461f79d6172c678279c5d5585befe
MD5 2c5cb713e91a526c18b9bfdf9ba89ca5
BLAKE2b-256 541d9d5bb8307556802ddee07189177d6d21c116645d6b79841a8bfc32f68a62

See more details on using hashes here.

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

Hashes for decoy-2.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 7ddcc08b8ce991f7705cee76fae9061dcb17352e0a1ca2d9a0d4a0306ebd51cd
MD5 9ddc41bc8e9ae6ce5a8aafc7c4231e95
BLAKE2b-256 a2841a324d1cfebd8b23d29df95239e2a276b902a32b3127f3a62638b8eae3f5

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page