"""把事件出口契约接到一个测试替身上。 库不带这个接缝的实现——带了就等于替某一家定了投递协议。这里造一个最小的替身,它存在的唯一 目的是让套件的每一条用例至少被真的求值一次。 **这个替身住在 `tests/` 里,不进 wheel,任何下游都拿不到它。** 「库不带默认实现」那条禁的是 `src/` 下出现一个能用的实现——下游装了包就拿得到,就会有人直接用。判据是下游拿不拿得到, 不是代码库里有没有一个能跑的实现 (`research-wiki/design/0014-contract-suite-distribution.md` 决策六)。 `contract` 这个标记打在本文件上,不打在套件里,理由见 `test_run_stores.py`。 """ from collections.abc import Mapping import pytest from polyloop.ports import Event from polyloop.testing import EventSinkContract pytestmark = pytest.mark.contract class _CollectingEventSink: """收下事件,攒进一个列表。 **不做别的**:这套契约只断言「收得下一个事件」,而「投递失败之后库还在跑」「库没有把失败 再发一次」都是整次运行的行为,由库自己的测试守着,不由一个出口实现验。往这里加重试、加 过滤、加计数,验的就变成这个替身自己了。 它满足 `polyloop.ports.EventSink`,但不显式继承那个 Protocol:结构化子类型不需要继承。 """ def __init__(self) -> None: self.events: list[Event] = [] async def emit(self, event: Event) -> None: self.events.append(event) def parameters(self) -> Mapping[str, str]: return {"kind": "collecting"} class TestCollectingEventSink(EventSinkContract): @pytest.fixture def event_sink(self) -> _CollectingEventSink: return _CollectingEventSink()