← Blog

Mocks lie: why integration branches need real providers

Integration code fails in the seams, and the seams are exactly what mocks do not model. A mocked Slack client will accept a scope your app was never granted. A fake webhook endpoint never checks a signature. A stubbed OAuth flow skips the redirect URI allowlist that production enforces to the character. The failures that hurt are provider-side behavior: signature verification with the real signing secret, token exchange against the real grant type, and event payloads in the provider's current shape instead of a fixture frozen last quarter. None of that is reachable from a unit test.

A mock validates your assumptions. The provider validates your code.

Why shared staging does not save you

Teams often route around mocks with one shared staging app for each provider and inherit a different failure: drift. The branch that needs issues:write edits the shared Linear app, and every other branch now tests against scopes production does not have. Webhooks point at whoever edited the console last. Nobody can validate a scope change safely because everybody shares one contract.

Per-branch, or it did not happen

The unit of isolation has to be the branch. A branch that changes the integration contract gets provider apps matching its permissions, webhook events, and callbacks, resolved to its preview URL. Shared staging stays untouched. That used to mean an afternoon of console work for every branch. Minting makes it one command. Mocks still belong in fast unit suites. They simply cannot sign off on the integration seams. Cleanup completes the contract by removing branch resources after the work merges while keeping the evidence a reviewer needs.