pytest-when
Inspired
by mokito-scala, pytest-when
provides a fixture for pytest to simplify the mocking of python objects:
Purpose
More readable than the full Given...When...Then pattern, pytest-when is
meant for developers who want to test for behaviour, without any extra
overhead.
Enable the mock only for a specific argument's values to make code more
readable.
Benefits
In this example, when you specify the first two arguments and any third argument, the attribute will be mocked,
(
when(some_object, "attribute")
.called_with(1, 2, when.markers.any)
.then_return("attribute mocked")
# or
# .then_call(some_callable)
# or
# .then_raise(SomeException())
)
Note that the .called_with method arguments are compared with the real
callable signature.
This gives additional protection against changing the real callable interface.
With when fixture, the following expression:
when(example_module, "some_normal_function").called_with(
"a",
1,
kwarg1="b",
kwarg2=2,
).then_return("Mocked")
is roughly equal to:
mock_only_for_calls = (
call("a", 1, kwarg1="b", kwarg2=2),
"Mocked",
)
def matches(
call: Call,
mocked_calls_registry: tuple[tuple[call, ReturnType], ...],
) -> bool:
...
def create_call(*args, **kwargs) -> Call:
...
def side_effect_callback(*args, **kwargs):
if matches(create_call(*args, **kwargs), mock_only_for_calls):
return mock_only_for_calls[1]
return unittest.mock.DEFAULT
mocker.patch.object(
example_module,
"some_normal_function",
autospec=True,
side_effect=side_effect_callback,
)
where logic of matches and create_call is not trivial
Installation
Install the package into your development environment, from
pypi, using pip, for example:
pip install pytest-when
Implementation
Onced installed, the when fixture will be available just like the rest of
the pytest plugins.
See the following example of how to use it:
# class which we're going to mock in the test
class Klass1:
def some_method(
self,
arg1: str,
arg2: int,
*,
kwarg1: str,
kwarg2: str,
) -> str:
return "some_method not mocked"
def test_should_properly_patch_calls(when):
when(Klass1, "some_method").called_with(
"a",
when.markers.any,
kwarg1="b",
kwarg2=when.markers.any,
).then_return("some method mocked")
assert (
Klass1().some_method(
"a",
1,
kwarg1="b",
kwarg2="c",
)
== "some method mocked"
)
assert (
Klass1().some_method(
"not mocked param",
1,
kwarg1="b",
kwarg2="c",
)
== "some method not mocked"
)
# if you need to patch a function
def test_patch_a_function(when):
when(example_module, "some_normal_function").called_with(
"a",
when.markers.any,
kwarg1="b",
kwarg2=when.markers.any,
).then_return("some_normal_function mocked")
assert (
example_module.some_normal_function(
"a",
1,
kwarg1="b",
kwarg2="c",
)
== "some_normal_function mocked"
)
assert (
example_module.some_normal_function(
"not mocked param",
1,
kwarg1="b",
kwarg2="c",
)
== "some_normal_function not mocked"
)
It is possible to use when with class methods and standalone functions
(in this case cls parameter will become a python module).
You can patch the same object multiple times using different called_with
parameters in a single test.
You can also patch multiple targets (cls, method)
See more examples at: test_integration
Setup for local developement
The project can be extended by cloning the repo and
installing the PDM build tool
So, the development environment requires:
- pdm https://pdm.fming.dev/latest/#installation
- python3.8 or greater
pdm install
To run tests and linters use:
make test
make lint
Metadata
Release files for pytest-when 2.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| pytest_when-2.3.0.tar.gz | 11.0 kB | Without provenance | Details for pytest_when-2.3.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| pytest_when-2.3.0-py3-none-any.whl | Python 3 | none | any | Details for pytest_when-2.3.0-py3-none-any.whl |
Total release size: 20.6 kB
Release files / pytest_when-2.3.0.tar.gz
| Download URL | pytest_when-2.3.0.tar.gz |
|---|---|
| Size | 11.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6edf6bd44508328b74bc0f7859e8128059ba015d2c924c0d3cc9cfd0231767a1
|
|
BLAKE2b-256 checksum How to use checksums |
30a12ae7c2637a5e6e961edb9a7a716e6fc1330dfc6439b50edde0eecce97a08
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
pdm/2.25.9 CPython/3.12.3 Linux/6.11.0-1018-azure
|
Release files / pytest_when-2.3.0-py3-none-any.whl
| Download URL | pytest_when-2.3.0-py3-none-any.whl |
|---|---|
| Size | 9.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
fc7e184f288416d7db4010d1cea667ea60f65a742559fdce90f26fd37d071065
|
|
BLAKE2b-256 checksum How to use checksums |
74048e032e875a3affb86c8293b8e41d74cd2ea214473051414525e684e2e2d4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
pdm/2.25.9 CPython/3.12.3 Linux/6.11.0-1018-azure
|
Security for pytest-when 2.3.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.