How to Mock a Slow Startup Probe in Python
Simulate slow service initialization with a configurable mock delay to test readiness probes.
Python code
39 linesimport 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
[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
- Use `unittest.mock` with `patch` to replace `time.sleep` for faster tests.
- 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
More from Reliability & rate limiting
- At Least Once with Idempotent Consumer in Python medium
- Build a Rate Limiter Decorator in Python easy
- Build a queue-based admission control system in Python easy
- Chaos Inject Random Failures in Python easy
- Circuit breaker failure threshold count in Python medium
- Exactly Once Processing Dedupe Mock in Python easy
Keep learning
Related tutorials and quizzes for this topic.