> ## Documentation Index
> Fetch the complete documentation index at: https://docs.zespan.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Testing and mocking

> Disable Zespan in tests, mock the SDK for unit testing, and configure CI environments.

Zespan adds zero latency in production because events are batched asynchronously. In test environments, you want to ensure the SDK does not make network calls, slow down test suites, or leak API keys.

## Disable tracing in tests

Set `sampleRate` to `0` to drop all events before they reach the queue. No network calls are made.

```typescript theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
zespan.init({
  apiKey: process.env.ZESPAN_API_KEY ?? "zsp_test",
  sampleRate: 0, // drop all events
  environment: "test",
});
```

You can also skip `zespan.init()` entirely in tests — the SDK is a no-op if not initialized. Calls to `wrapOpenAI()` and other wrappers return the original client unchanged.

## Disable via environment variable

If `ZESPAN_API_KEY` is not set, the SDK does not initialize. In CI, simply omit the variable:

```bash theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
# .env.test — no ZESPAN_API_KEY
OPENAI_API_KEY=sk-...
```

Or guard initialization in your application code:

```typescript theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
if (process.env.ZESPAN_API_KEY) {
  zespan.init({ apiKey: process.env.ZESPAN_API_KEY });
}
```

## Mock the SDK in unit tests

For unit tests that assert on span creation, mock the SDK module:

```typescript theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
// vitest
import { vi, describe, it, expect } from "vitest";

vi.mock("@zespan/sdk", () => ({
  zespan: {
    init: vi.fn(),
    wrapOpenAI: (client: unknown) => client, // return client unchanged
    wrapAnthropic: (client: unknown) => client,
  },
  withAgent: vi.fn(async (_opts, fn) => fn()),
  startSpan: vi.fn(async (_opts, fn) => fn({ setAttributes: vi.fn() })),
}));

describe("my agent", () => {
  it("calls the model once", async () => {
    // your test — Zespan SDK is a no-op
  });
});
```

## Use a test API key

If you want the SDK initialized in integration tests but do not want real traces sent to Zespan, set a dummy API key and point to a local mock server:

```typescript theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
zespan.init({
  apiKey: "zsp_test_dummy",
  endpoint: "http://localhost:4318", // local mock or equivalent
  environment: "test",
  sampleRate: 1.0,
});
```

## Flush in tests

If your test runner exits before the SDK flushes its event queue, traces may be silently dropped. Call `zespan.getClient().flush()` at the end of each test:

```typescript theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
afterEach(async () => {
  await zespan.getClient().flush();
});
```

## CI environment configuration

In CI (GitHub Actions, CircleCI, etc.), set `environment` to `"ci"` and `sampleRate` to `0`:

```yaml theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
# .github/workflows/test.yml
env:
  ZESPAN_API_KEY: ${{ secrets.ZESPAN_API_KEY }}
  ZESPAN_SAMPLE_RATE: "0"
  ZESPAN_ENVIRONMENT: "ci"
```

The SDK reads `ZESPAN_SAMPLE_RATE` as a number between `0.0` and `1.0`. Set it to `0` to drop all events in CI without changing application code.

## Next steps

* [Environments](/guides/environments) — separate production, staging, and development traces
* [SDK configuration](/sdk/typescript) — full init options reference
