https://github.com/konradhalas/mimid
Modern mocking library for Python.
https://github.com/konradhalas/mimid
mocking software-development tdd testing
Last synced: 3 months ago
JSON representation
Modern mocking library for Python.
- Host: GitHub
- URL: https://github.com/konradhalas/mimid
- Owner: konradhalas
- License: mit
- Created: 2019-06-09T20:49:57.000Z (about 7 years ago)
- Default Branch: master
- Last Pushed: 2022-12-21T11:18:48.000Z (over 3 years ago)
- Last Synced: 2025-03-27T21:52:07.975Z (about 1 year ago)
- Topics: mocking, software-development, tdd, testing
- Language: Python
- Homepage:
- Size: 58.6 KB
- Stars: 11
- Watchers: 0
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# mimid
[](https://travis-ci.org/konradhalas/mimid)
[](https://coveralls.io/github/konradhalas/mimid?branch=master)
[](https://pypi.python.org/pypi/mimid/)
[](https://pypi.python.org/pypi/mimid/)
[](https://pypi.python.org/pypi/mimid/)
[](https://github.com/ambv/black)
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
```python
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:
1. [Creation](#creation)
2. [Configuration](#configuration)
3. [Verification](#verification)
Additionally you can use [matchers](#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:
```python
from mimid import mock
class A:
def foo(self, param):
pass
class_mock = mock(A)
```
Function example:
```python
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.
```python
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.
```python
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:
```python
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`.
```python
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:
```python
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:
```python
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:
```python
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][halas-homepage].
[halas-homepage]: https://konradhalas.pl
[mockito]: https://site.mockito.org
[mockk]: https://github.com/mockk/mockk