punit.mocks#

Provides mocking facilities via a m:class:Mock class and/or a m:class:patch class.

Usage:

from punit.mocks import Mock, is_any, contains, patch

# Fluent syntax
mock = (
    Mock()
    .do_stuff.returns(42)

)

# Constructor kwargs for fixture-style initialization
user = Mock(first_name='Alice', email='alice@example.com')
assert user.first_name == 'Alice'
assert user.email == 'alice@example.com'

# Matcher-based verification
assert mock.called_with(
    is_any(),
    neg(contains('foo')),
    is_in(1, 2, 3))

# Module-level patching
with patch('some.module.ClassName') as m:
    m.method.returns('result')
class Call(*args: Any, **kwargs: Any)#

Bases: object

Immutable record of a single mock call.

Call records carry the full metadata set (timestamp, took, is_async, result, error) so that .calls and .mock_calls return semantically identical data.

Variables:
  • path – Absolute dotted path name (e.g. 'Mock.foo.bar').

  • timestamp – Time when the call occurred (time.monotonic_ns()).

  • took – Time spent in the call, in seconds.

  • is_async – Whether the call was made via await.

  • args – Positional arguments passed to the mock.

  • kwargs – Keyword arguments passed to the mock.

  • result – Return value from the call (None if no return value).

  • error – Exception raised by the call (None if none).

Examples:

>>> Call('Mock.foo', (1,), {'key': 'val'})
>>> Call(path='Mock.foo', timestamp=42.0, took=0.001, is_async=False, args=(1,), kwargs={'key': 'val'}, result='r', error=None)
path: str = ''#
timestamp: float = 0.0#
took: float = 0.0#
is_async: bool = False#
args: tuple[Any, ...] = ()#
kwargs: dict[str, Any]#
result: Any = None#
error: BaseException | None = None#
class CallList(iterable=(), /)#

Bases: tuple

Tuple of Call supporting partial-sublist matching via __contains__.

class Matcher#

Bases: ABC

Base class for argument matchers.

Subclasses must implement __eq__(self, other: Any) -> bool and return True when other matches the expected pattern. This allows Mock.called_with() to dispatch via Python’s equality operator naturally.

class Mock(origin=None, *, delegate=None, name='Mock', returns=None, **kwargs)#

Bases: object

Lightweight mock object for dependency injection testing.

Every Mock instance can register itself as a virtual subclass of any type (ABC, @runtime_checkable Protocol, or concrete class) via the origin parameter – making isinstance(mock, origin) return True.

Usage:

from punit.mocks import Mock

# Create a mock that conforms to UserService structurally
mock = Mock(origin=UserService)
mock.is_authenticated.returns(False)
mock.get_user.returns('Guest')

assert mock.called_with(42)

Child mocks (returned by attribute access) are cached – mock.foo is mock.foo.

Create a new Mock instance.

Parameters:
  • origin (Optional[type]) – The type this mock stands in for (enables isinstance checks).

  • delegate (Any) – A real object whose methods are forwarded when not configured.

  • name (str) – Debug identifier for the mock. Defaults to 'Mock'.

  • validate – If True, validate call arguments against inspectable signatures.

  • returns (Any) – A convenience kwarg that assigns a return value for the Mock, similar to calling returns(…).

  • kwargs (Any) – Arbitrary keyword arguments set as initial attribute values. Each key becomes an accessible attribute that returns the given value. The special key side_effect is applied to this mock’s calling behavior.

classmethod register_origin(origin)#

Register origin so that Mock instances pass isinstance(_, origin).

Dispatches to the origin’s register method (for ABCs and runtime_checkable Protocols).

Parameters:

origin (type) – The type this mock stands in for.

Return type:

None

property all_calls: CallList#

Aggregate of self-invokations and child-invokations.

property call_count: int#

Number of calls recorded for this mock.

property calls: Sequence[Call]#

Immutable sequence of all recorded calls.

property called: bool#

Return True if this mock has been called (self-invocations.)

property child_calls: CallList#

Calls reached through child attribute access only (not self-invocations.)

property mock_calls: CallList#

All calls to this mock (self-invocations.)

property origin: type | None#

The origin type this mock stands in for.

property side_effect: Callable[[Callable[[...], Any] | BaseException | type | Iterable[Any] | None], Mock]#

Set side effect (callable/exception/iterable). Clears returns.

when(*args, **kwargs)#

Create a conditionally-dispatched subgraph mock keyed by matcher arguments.

Identical matcher tuples always return the same subgraph (dedup via canonical name). The matched subgraph’s __call__ is forwarded matching call args for dispatch to further nested conditions or flat config.

Raises:

MockError – if no matcher arguments are provided (ambiguous condition).

Return type:

Mock

returns(value_or_callable)#

Set fixed return value or callable. Callable receives the mocked instance as its sole argument. Clears side_effect.

Return type:

Mock

reset(*, preserve_stubs=True, preserve_sideeffects=True)#

Reset this mock’s call tracking and optionally its configuration.

Parameters:
  • preserve_stubs (bool) – If True (default), retain child stubs created by attribute access or from an origin. If False, recursively clear all children so that subsequent attribute access creates fresh mocks.

  • preserve_sideeffects (bool) – If True (default), keep fluent-configuration values such as __return_value__ and __side_effect__ intact. If False, wipe all __*-prefixed* configuration keys from ``_u.configured and reset the has_* flags, but leave structural stubs (origin-prepopulated members) untouched.

Return type:

None

called_with(*args, **kwargs)#
Return type:

bool

Return True if any recorded call matches args and **kwargs.

Uses == dispatch for each argument, enabling matcher support.

exception MockError#

Bases: Exception

Exception raised when mock configuration is violated.

class neg(inner)#

Bases: Matcher

Wraps another matcher and negates its result.

This enables composing matchers freely – e.g. neg(is_in('admin', 'root')) matches any value that is not ‘admin’ or ‘root’.

Parameters:

inner (Matcher) – The matcher to negate.

Returns:

A Matcher instance.

property inner: Matcher#
contains(value)#

Return a matcher that checks if value is a substring of a string or an element of a container (list, tuple, set, dict keys).

Parameters:

value (Any) – The value to search for.

Return type:

Matcher

Returns:

A Matcher instance.

is_any()#

Return a singleton matcher that matches any single value.

Return type:

Matcher

Returns:

A Matcher instance.

is_gte(n)#

Return a matcher that checks if the value is greater than or equal to n.

Parameters:

n (float) – The threshold to compare against.

Return type:

Matcher

Returns:

A Matcher instance.

is_gt(n)#

Return a matcher that checks if the value is strictly greater than n.

Parameters:

n (float) – The threshold to compare against.

Return type:

Matcher

Returns:

A Matcher instance.

is_in(*values)#

Return a matcher that checks if the value equals one of the provided values.

This is the inverse of contains()contains(x) checks if x is in the arg, while is_in(a, b, c) checks if the arg is one of a, b, or c.

Parameters:

values (Any) – The candidate values to check against.

Return type:

Matcher

Returns:

A Matcher instance.

is_lte(n)#

Return a matcher that checks if the value is less than or equal to n.

Parameters:

n (float) – The threshold to compare against.

Return type:

Matcher

Returns:

A Matcher instance.

is_lt(n)#

Return a matcher that checks if the value is strictly less than n.

Parameters:

n (float) – The threshold to compare against.

Return type:

Matcher

Returns:

A Matcher instance.

is_type(*types)#

Return a matcher that checks if the value is an instance of any given type(s).

Parameters:

types (type) – One or more types to check against.

Return type:

Matcher

Returns:

A Matcher instance.

class patch(target_path, origin=None, **kwargs)#

Bases: object

Patch a module-level attribute with a Mock.

Can be used as both a context manager and a decorator. The same instance handles both via __enter__/__exit__ and __call__.

Usage:

# As context manager:
with patch('myapp.db.connect') as mock_connect:
    mock_connect.returns('connected')

# As decorator:
@patch('myapp.db.connect')
def test_something(m):
    assert m.called

Create a new patch for the given dotted path.

Parameters:
  • target_path (str) – Dotted attribute path to replace (e.g. 'myapp.database.connect').

  • origin (Optional[type]) – Optional type for Mock virtual-subclass registration.

  • kwargs (Any) – Additional keyword arguments forwarded to the Mock constructor.