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
Release history Release notifications | RSS feed
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
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pl_mocks_and_fakes-0.0.34.tar.gz.
File metadata
- Download URL: pl_mocks_and_fakes-0.0.34.tar.gz
- Upload date:
- Size: 8.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d05bedb7cf74600b187563dd7f68fb6cd0a9bc5492e651d4ee9b81d7a63ea861
|
|
| MD5 |
b62739087ac87ef67678255fcf545a9b
|
|
| BLAKE2b-256 |
b4c69094f0fa7fe5757cf14e9a81484aeb6f4ee19cabdd478f779ba0e615bc54
|
File details
Details for the file pl_mocks_and_fakes-0.0.34-py3-none-any.whl.
File metadata
- Download URL: pl_mocks_and_fakes-0.0.34-py3-none-any.whl
- Upload date:
- Size: 11.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a25c79f89bb45c7f96256dd03e9104290e2ff26b34995cc8166e501a7d14a3b6
|
|
| MD5 |
1c932bbe196f7b6d04277f2b341d0133
|
|
| BLAKE2b-256 |
a979a9cccc6b4e535e61c4a1a6b0e2c828edbf5d63c6d375f964d5a7000f5b85
|