Skip to main content

Mock slow, nondeterministic, and side-effect-producing code with minimal per-test configuration.

Project description

pl-mocks-and-fakes

Mock slow, nondeterministic, and side-effect-producing code with minimal per-test configuration.

Project Status

Alpha. Expect breaking changes.

Installation

uv add pl-mocks-and-fakes

Usage (Mocks)

# your_package/your_module.py

from pl_mocks_and_fakes import MockInUnitTests, MockReason
import random

@MockInUnitTests(MockReason.NONDETERMINISTIC)
def random_int() -> int:
    return random.randint(0, 100)

@MockInUnitTests(MockReason.NONDETERMINISTIC)
def random_string() -> str:
    return random.choice(["foo", "bar", "baz"])

def random_int_and_string() -> tuple[int, str]:
    return random_int(), random_string()



# your_test_package/conftest.py

import pytest
from pl_mocks_and_fakes import initialize_mocks
import your_test_package

def pytest_runtest_setup(item: pytest.Item) -> None:
    initialize_mocks(your_test_package)



# your_test_package/your_module_test.py

from pl_mocks_and_fakes import stub, mock_for
from your_package.your_module import random_int, random_int_and_string, random_string

def test_random_int_and_string() -> None:
    # Use `stub` to set the return value of a mock for a specific test.
    stub(random_int)(5)
    # Use `mock_for` to get the Mock object.
    mock_for(random_string).return_value = "foo"

    result = random_int_and_string()

    assert result == (5, "foo")

Usage (Fakes)

# your_package/jira_api_client.py

from dataclasses import dataclass

from pl_mocks_and_fakes import Fake, MockInUnitTests, THIRD_PARTY_API_MOCK_REASONS

@dataclass
class JiraTicket:
    id: str
    title: str


@MockInUnitTests(*THIRD_PARTY_API_MOCK_REASONS)
def create_jira_ticket(title: str) -> str:
    # This makes a third-party API call.
    # ...
    pass

@MockInUnitTests(*THIRD_PARTY_API_MOCK_REASONS)
def fetch_jira_ticket(ticket_id: str) -> JiraTicket:
    # This makes a third-party API call.
    # ...
    pass

def duplicate_jira_ticket(ticket_id: str) -> str:
    ticket = fetch_jira_ticket(ticket_id)
    return create_jira_ticket(ticket.title)



# your_test_package/conftest.py

import pytest
from pl_mocks_and_fakes import create_fakes, initialize_mocks
import your_test_package

def pytest_runtest_setup(item: pytest.Item) -> None:
    initialize_mocks(your_test_package)
    create_fakes(your_test_package)



# your_test_package/jira_fake.py

from pl_mocks_and_fakes import Fake, mock_for
from your_package.jira_api_client import JiraTicket, create_jira_ticket, fetch_jira_ticket

class JiraFake(Fake):
    def __init__(self):
        def _create_jira_ticket_side_effect(title: str) -> str:
            ticket_id = f"FAKE-{len(self.tickets) + 1}"
            self.tickets.append(JiraTicket(id=ticket_id, title=title))
            return ticket_id

        def _fetch_jira_ticket_side_effect(ticket_id: str) -> JiraTicket:
            for ticket in self.tickets:
                if ticket.id == ticket_id:
                    return ticket
            raise ValueError(f"Ticket with id {ticket_id} not found")

        self.tickets: list[JiraTicket] = []
        mock_for(create_jira_ticket).side_effect = _create_jira_ticket_side_effect
        mock_for(fetch_jira_ticket).side_effect = _fetch_jira_ticket_side_effect

    def create_jira_ticket(self, title: str) -> str:
        return mock_for(create_jira_ticket).side_effect(title)

    def fetch_jira_ticket(self, ticket_id: str) -> JiraTicket:
        return mock_for(fetch_jira_ticket).side_effect(ticket_id)



# your_test_package/your_module_test.py

from pl_mocks_and_fakes import fake_for
from your_package.jira_api_client import duplicate_jira_ticket
from your_test_package.jira_fake import JiraFake

def test_duplicate_jira_ticket() -> None:
    # Use `fake_for` to get the Fake object.
    ticket_id = fake_for(JiraFake).create_jira_ticket("Ticket Name")

    duplicated_ticket_id = duplicate_jira_ticket(ticket_id)

    assert ticket_id != duplicated_ticket_id
    assert fake_for(JiraFake).fetch_jira_ticket(duplicated_ticket_id).title == "Ticket Name"
    assert len(fake_for(JiraFake).tickets) == 2

Releasing

Run ./release.sh.

License

Licensed under the Apache License 2.0. See LICENSE.

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

pl_mocks_and_fakes-0.0.42.tar.gz (9.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pl_mocks_and_fakes-0.0.42-py3-none-any.whl (11.4 kB view details)

Uploaded Python 3

File details

Details for the file pl_mocks_and_fakes-0.0.42.tar.gz.

File metadata

  • Download URL: pl_mocks_and_fakes-0.0.42.tar.gz
  • Upload date:
  • Size: 9.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for pl_mocks_and_fakes-0.0.42.tar.gz
Algorithm Hash digest
SHA256 19d2cec35a2e0f11794085380614e5e4252441e8593072ab785a0761d8c05373
MD5 a86a3a4d77c33d522846dd5d7a23ebb1
BLAKE2b-256 6dc46ffcf9f0213b6b921ebd3584bf05b70d0c7fa958fdc335c3a5cce1ccdb86

See more details on using hashes here.

File details

Details for the file pl_mocks_and_fakes-0.0.42-py3-none-any.whl.

File metadata

  • Download URL: pl_mocks_and_fakes-0.0.42-py3-none-any.whl
  • Upload date:
  • Size: 11.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for pl_mocks_and_fakes-0.0.42-py3-none-any.whl
Algorithm Hash digest
SHA256 e72b6dd843321b3dc3bcae8131a5392e9bf601f546ac36b3097c66ce19bde2a5
MD5 84d85c379e05cdf3f8b5ffe4248b046d
BLAKE2b-256 41e6860d72cecb434d6dd7f1646f6057433b39d1790f960db682715947c4981a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page