How to Mock a Slow Startup Probe in Python

Simulate slow service initialization with a configurable mock delay to test readiness probes.

Easy Python 3.9+ Aug 9, 2026 Reliability & rate limiting 13 views 0 copies

Python code

39 lines
Python 3.9+
import time
from dataclasses import dataclass, field


@dataclass
class StartupProbe:
    name: str
    min_wait_sec: float = 0.5
    max_wait_sec: float = 2.0
    _ready: bool = field(default=False, init=False, repr=False)

    def initialize(self) -> None:
        """Simulate slow startup with a fixed mock delay."""
        delay = self.min_wait_sec + (self.max_wait_sec - self.min_wait_sec) / 2
        print(f"[{self.name}] Initializing... (mock delay {delay:.2f}s)")
        time.sleep(delay)
        self._ready = True
        print(f"[{self.name}] Ready.")

    @property
    def ready(self) -> bool:
        return self._ready


def probe(service: StartupProbe) -> bool:
    """Return readiness status after initialization."""
    if not service.ready:
        service.initialize()
    return service.ready


if __name__ == "__main__":
    db = StartupProbe("database", min_wait_sec=0.2, max_wait_sec=1.0)
    api = StartupProbe("api", min_wait_sec=0.5, max_wait_sec=1.5)

    start = time.time()
    print(f"DB ready: {probe(db)}")
    print(f"API ready: {probe(api)}")
    print(f"Total elapsed: {time.time() - start:.2f}s")

Output

stdout
[database] Initializing... (mock delay 0.60s)
[database] Ready.
DB ready: True
[api] Initializing... (mock delay 1.00s)
[api] Ready.
API ready: True
Total elapsed: 1.60s

How it works

The StartupProbe dataclass models a service with a configurable mock delay between min_wait_sec and max_wait_sec. The initialize method sleeps for a fixed midpoint delay to emulate slow startup, then sets the _ready flag. The probe function checks the ready property and triggers initialization only once, mimicking a typical readiness check. Using time.sleep simulates real-world latency, and the dataclass keeps the mock configurable and easy to test.

Common mistakes

  • Forgetting to use `init=False` on fields that should not be constructor arguments.
  • Not resetting the `_ready` flag between test runs, causing false readiness.
  • Using a fixed delay that is too long, slowing down test suites unnecessarily.

Variations

  1. Use `unittest.mock` with `patch` to replace `time.sleep` for faster tests.
  2. Implement a factory function that returns different mock implementations.

Real-world use cases

  • Simulating database or cache warm-up in integration tests to verify readiness endpoints.
  • Mocking external service latencies in CI pipelines to ensure timeouts are handled correctly.
  • Modeling startup delays for monitoring and alerting in development environments.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Reliability & rate limiting

Related tutorials and quizzes for this topic.