Testing & mocks
Keep most integration tests local, predictable, and free of side effects. Use a smaller set of explicit live checks to verify the real provider contract.
On this page
Test your application boundary
Inject the operation your product needs instead of constructing a live SDK client inside business logic. A deterministic fake lets you verify the inputs and outcomes that matter without imitating every internal detail of a provider library.
type EmailInput = { to: string; subject: string };
type EmailSender = {
send(input: EmailInput): Promise<{ id: string }>;
};
export async function sendWelcome(
sender: EmailSender,
recipient: string,
) {
return sender.send({
to: recipient.trim(),
subject: 'Welcome',
});
}
export function createFakeEmailSender() {
const calls: EmailInput[] = [];
const sender: EmailSender = {
async send(input) {
calls.push({ ...input });
return { id: 'email_fixture_001' };
},
};
return { sender, calls };
}Make fixtures deterministic
Use fixed identifiers and explicit error fixtures. Inject clocks, ID generators, and random-number sources when the behavior depends on them. Create a fresh fake for each test so execution order cannot change the result.
import test from 'node:test';
import assert from 'node:assert/strict';
import { createFakeEmailSender, sendWelcome } from './email';
test('welcome sends to the normalized recipient', async () => {
const { sender, calls } = createFakeEmailSender();
const result = await sendWelcome(
sender,
' reader@example.com ',
);
assert.equal(result.id, 'email_fixture_001');
assert.deepEqual(calls, [{
to: 'reader@example.com',
subject: 'Welcome',
}]);
});The example uses the built-in Node.js test runner. Run TypeScript through your project's configured test toolchain. The fake records what the welcome workflow actually sends, so the test checks recipient normalization and the product's chosen subject.
Cover the difficult paths
| Fixture | Behavior to verify |
|---|---|
| Invalid input | Validation fails before a provider request is made. |
| Unsupported capability | No empty-success response or accidental fallback. |
| Rate limit | The retry policy respects its deadline and attempt budget. |
| Timeout after submission | A side effect is not blindly repeated. |
| Partial result | Failed items remain visible alongside successful items. |
| Privacy restriction | No data is sent to an unapproved fallback provider. |
Separate live contract checks
Use dedicated credentials and test data, set a spending limit, and clean up created records. Require an explicit opt-in for tests that contact a provider. Never let a missing fixture or environment variable quietly turn a local test into a live request.
SDK SDK is an independent discovery hub. Provider examples link to official documentation. App-owned examples are illustrative patterns you can adapt.