How to simulate timeouts and duplicate event delivery in integration tests
Inject a lost response after a successful write, then assert the final record count. That single test catches the difference between "the request succeeded" and "the workflow is safe to retry".
Simulate a timeout after a write
The fault you want is timeout after write: the provider commits the write, but the response never reaches your code. Your application sees a failure and retries. Without a check for duplicates, the second request creates a second record.
In AgentTwin this is a declared fault rather than a timing hack. The run has three parts:
npx agenttwin example --out ./ex
npx agenttwin run --file ./ex/agenttwin.world.json
npx agenttwin run --file ./ex/agenttwin.world.json --fault timeout-after-write
The clean run passes with one ticket and one notification. The faulted run exits 1 because the final state contains two tickets. The receipt records the service events, the state delta and the failed assertion.
Simulate duplicate event delivery
A duplicate event is a different shape of the same failure: the provider delivered the event twice even though the workflow asked once. The right test is again a final-state assertion, not an event count alone. Reject if the workflow applies the event twice to a record that must be idempotent. Combine this with the timeout test when both can happen in the same window.
AgentTwin describes four named faults: timeout-after-write, delayed webhooks, duplicate event delivery and expired permissions. They are declared per test rather than configured as arbitrary network behaviour, so an untriggered fault is reported as incomplete rather than passing.
Replay the failure you found
Once the faulted run is recorded, replaying it reopens the captured application, world and checks. The observed reproduction in this article used the same seed and recorded state; no assertion changed between the two runs.
npx agenttwin replay RUN_ID
The useful signal is identical reproduction. If a repeated replay produces different events, the scenario depends on hidden state and is not yet a reliable regression.
Tradeoffs
- Timeouts approximate a provider that accepted work but lost its response. They do not reproduce network routing, OS scheduling or provider outage duration.
- Duplicate delivery is not the same as two distinct events. Decide which one your assertion should reject before writing it.
- A passing replay proves the recorded assertions still hold under that captured state; it does not prove that production providers behave the same way.
Related guides: AgentTwin vs WireMock, workflow outcomes and fault coverage, supported provider operations.