Skip to main content

ExtendedMock Pytest Plugin

Welcome to the ExtendedMock Pytest Plugin! This plugin enhances Python's unittest.mock.MagicMock with additional functionality inspired by the setup and verification patterns found in popular .NET mocking libraries like Moq. If you've ever used Moq and loved its fluent API for configuring mock behavior, this plugin will feel like home.

What is ExtendedMock?

ExtendedMock is a drop-in replacement for unittest.mock.MagicMock that adds a setup method, allowing you to configure mock behavior for specific arguments. This makes it easier to write expressive and precise tests by defining exactly what your mock should return (or raise) when called with certain arguments.

Key Features:

  • Fluent API: Configure mock behavior using a clean, chainable setup method.
  • Argument-Specific Behavior: Define return values or exceptions for specific argument combinations.
  • Opt-in: Use ExtendedMock where you want it, directly or through mocker.patch(..., new_callable=ExtendedMock). Every other MagicMock is left alone.
  • Still a MagicMock: Calls are recorded, so assert_called_with and friends keep working alongside setup.
  • Familiar to .NET Developers: If you've used Moq, you'll feel right at home with the setup method.

Usage

install

pip install pytest-extended-mock

Basic Example

Here's how you can use ExtendedMock in your tests:

from pytest_extended_mock import ExtendedMock

def test_extended_mock():
    mock = ExtendedMock()
    
    # Configure the mock to return "Hello, World!" when called with ("foo", bar=42)
    mock.setup("foo", bar=42, return_value="Hello, World!")
    
    # Call the mock with the configured arguments
    result = mock("foo", bar=42)
    
    assert result == "Hello, World!"

Example with mocker.patch

from pytest_extended_mock import ExtendedMock

def test_mocker_patch(mocker):
    mock = mocker.patch("your_path", new_callable=ExtendedMock)

    mock.setup("foo", return_value="bar")

    result = mock("foo")

    assert result == "bar"

Raising Exceptions

You can also configure the mock to raise an exception, given as a class or an instance, for specific arguments:

def test_extended_mock_with_exception():
    mock = ExtendedMock()
    
    # Configure the mock to raise a ValueError when called with ("error",)
    mock.setup("error", raises=ValueError("Something went wrong!"))
    
    # Call the mock with the configured arguments
    with pytest.raises(ValueError):
        mock("error")

Default Behavior

If the mock is called with arguments that don't match any configured setup, it falls back to the default MagicMock behavior and returns its return_value:

def test_extended_mock_default_behavior():
    mock = ExtendedMock()
    mock.setup("configured", return_value="result")
    mock.return_value = "default"
    
    assert mock("unconfigured", args=123) == "default"

Matchers

Setups are compared with ==, so arguments don't need to be hashable, and matchers such as unittest.mock.ANY work:

from unittest.mock import ANY

def test_extended_mock_any():
    mock = ExtendedMock()
    mock.setup(ANY, [1, 2], return_value="result")
    
    assert mock("anything", [1, 2]) == "result"

When more than one setup matches, the most recent one wins.


Why Use ExtendedMock?

If you've ever found yourself writing repetitive code to configure MagicMock instances for different argument combinations, ExtendedMock is here to save the day. It provides a more expressive and concise way to define mock behavior, making your tests easier to read and maintain.

For .NET Developers

If you're coming from the .NET world and have used libraries like Moq, you'll find the setup method very familiar. It mirrors the Setup and Returns methods in Moq, allowing you to define mock behavior in a similar way. For example:

// Moq in .NET
var mock = new Mock<IService>();
mock.Setup(x => x.DoSomething("foo", 42)).Returns("Hello, World!");
# ExtendedMock in Python
mock = ExtendedMock()
mock.do_something.setup("foo", 42, return_value="Hello, World!")

How It Works

The ExtendedMock class extends unittest.mock.MagicMock. Each setup call stores the expected call and sets the mock's side_effect to a function that compares each call against the stored setups. A match returns the configured value or raises the configured exception; anything else falls back to the mock's return_value. Because setup uses side_effect, it replaces any side_effect you set yourself. Attributes of an ExtendedMock are ExtendedMocks too, so mock.service.fetch.setup(...) works.


Contributing

We welcome contributions! If you have ideas for improvements or find a bug, please open an issue or submit a pull request on GitHub.


License

This project is licensed under the MIT License.


Keywords

  • pytest
  • mocking
  • unittest
  • MagicMock
  • Moq
  • .NET
  • testing
  • fluent API
  • mock setup

Happy testing! 🚀

Metadata

Release files for pytest-extended-mock 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pytest-extended-mock 0.2.0
File Size Uploaded Provenance Actions
pytest_extended_mock-0.2.0.tar.gz 3.8 kB Without provenance Details for pytest_extended_mock-0.2.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for pytest-extended-mock 0.2.0
File Interpreter ABI Platform Actions
pytest_extended_mock-0.2.0-py3-none-any.whl Python 3 none any Details for pytest_extended_mock-0.2.0-py3-none-any.whl

Total release size: 8.5 kB

Release files / pytest_extended_mock-0.2.0.tar.gz

Download URL pytest_extended_mock-0.2.0.tar.gz
Size 3.8 kB
Tags Source
SHA-256 checksum
How to use checksums
24d36393c7b33c7a5f9c169896c59b0618b01d0644ec81b5525a16181f78a0c9
BLAKE2b-256 checksum
How to use checksums
3f9cc05252662acbf9c3817a5cd76b4429c4b6eaa90fd817da37e1a7db8a32a4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.5.1 CPython/3.12.2 Darwin/27.0.0

Release files / pytest_extended_mock-0.2.0-py3-none-any.whl

Download URL pytest_extended_mock-0.2.0-py3-none-any.whl
Size 4.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
01d38690f3c00c938e6ce7b04de62847b81635976656eb6eb3799275ef912e0a
BLAKE2b-256 checksum
How to use checksums
348a4acf5762c59814fc1dd0857abd20f02ee829af09fbae24fce09f7aa99d1b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.5.1 CPython/3.12.2 Darwin/27.0.0

Security for pytest-extended-mock 0.2.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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page