Modern mocking library for Python.
Project description
mimid
Modern mocking library for Python.
⚠️ This project is under heavy development, API could be unstable.
Installation
To install mimid
, simply use pip
:
$ pip install mimid
Quick start
from mimid import mock, every, verify, any, gt
def add(a: int, b: int) -> int:
return a + b
def test_add():
add_mock = mock(add)
every(add_mock).returns(5)
result = add_mock(2, 2)
assert result == 5
verify(add_mock).with_args(any(), gt(0)).called(times=1)
Features
Mimid supports following features:
- easy mock behaviour configuration and verification
- works with classes and plain functions
- fully type hinted - it works with IDE's and type checkers
- clean API - not too much magic
Why not mock
?
Python built-in mock
module is an awesome tool. It's a first choice if you want to mock something in your tests.
However it has a few disadvantages:
- it doesn't work well with modern IDEs (e.g. auto completion) and type checkers
- it's difficult to define different behaviours for different cases
- it allows too much freedom, you can do anything with your mock object, even if you didn't define any behaviour
Inspiration
Mimid is highly inspired by mocking frameworks from a JVM world, like mockito or mockk.
Usage
There are 3 simple steps in the mimid
mocking workflow:
Additionally you can use matchers in both configuration and verification steps.
Creation
You have to use mock
function to create your mock object. It works both with classes and functions.
Class example:
from mimid import mock
class A:
def foo(self, param):
pass
class_mock = mock(A)
Function example:
from mimid import mock
def foo(param):
pass
function_mock = mock(foo)
Configuration
Before you call your mock (function or method) you have to configure its behaviour. Use every
with additional
methods (returns
, raises
, ...) to define how it should works during your test.
from mimid import mock, every
def foo(param):
pass
function_mock = mock(foo)
every(function_mock).returns(1)
You can also specify arguments which should trigger defined behaviour.
from mimid import mock, every
def foo(param):
pass
function_mock = mock(foo)
every(function_mock).with_args(param=2).returns(1)
every(function_mock).with_args(param=3).raises(Exception())
If you want to define property behaviour you have to use prop
function:
from mimid import mock, every, prop
class A:
@property
def x(self) -> int:
pass
class_mock = mock(A)
every(prop(class_mock).x).returns(1)
Available configurations:
Configuration | Description |
---|---|
returns |
return given value |
returns_many |
return each value from provided list |
raises |
raise given exception |
execute |
call given callable |
Verification
At the end of your test you can check if mock was called as expected with verify
.
from mimid import mock, verify
def foo(param):
pass
function_mock = mock(foo)
... # mock calls
verify(function_mock).called(times=2)
You can use the same with_args
also during verification step:
from mimid import mock, verify
def foo(param):
pass
function_mock = mock(foo)
... # mock calls
verify(function_mock).with_args(param=1).called(times=2)
Matchers
You can use matchers during configuration (with_args
) and verification (with_args
, called
) steps. You can also combine matchers with |
or &
and negate it with ~
.
Example:
from mimid import mock, every, verify, gt, lt, gte
def foo(param):
pass
function_mock = mock(foo)
every(function_mock).with_args(gt(0)).returns(1)
result = function_mock(10)
assert result == 1
verify(function_mock).with_args(gt(5) | lt(15)).called(times=gte(1))
capture
is a special matcher - it behaves like any()
but additionally it
stores given argument in provided slot.
Example:
from mimid import mock, every, slot, capture
def foo(param):
pass
function_mock = mock(foo)
param_slot = slot()
every(function_mock).with_args(capture(param_slot)).execute(lambda: param_slot.value + 1)
result = function_mock(1)
assert result == 2
assert param_slot.value == 1
Available matchers:
Matcher | Description |
---|---|
any |
match any value |
eq |
match equal value |
lt |
match lower value |
lte |
match lower or equal value |
gt |
match greater value |
gte |
match greater or equal value |
capture |
capture provided argument |
Authors
Created by Konrad Hałas.
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
Built Distribution
File details
Details for the file mimid-0.0.10.tar.gz
.
File metadata
- Download URL: mimid-0.0.10.tar.gz
- Upload date:
- Size: 9.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.1 CPython/3.11.1
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 165542c11de4c803315ccc5518ab934351d82d84fc715040468b018ef65a7c1c |
|
MD5 | ea3421515f6579c0a60aed43e0ae7502 |
|
BLAKE2b-256 | de3526182776ea7b0c1cb970a4c98f47a53414d215b7439e72e157cd13fae938 |
File details
Details for the file mimid-0.0.10-py3-none-any.whl
.
File metadata
- Download URL: mimid-0.0.10-py3-none-any.whl
- Upload date:
- Size: 9.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.1 CPython/3.11.1
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | ab28ce47a9ac4012c9186435a9fdac63df04991ace9fc76856e5bfedc16224f1 |
|
MD5 | 8617a574db024f58d045be24e753d465 |
|
BLAKE2b-256 | 177e7973005e2d4e43db450963dd2b47cc7393a7ad993e117dba9f927d5e8f0b |