llmao

How to mock the Anthropic SDK (Claude) in Jest and Vitest

llmao implements the @anthropic-ai/sdk client: messages.create(), streaming, messages.stream(), extended thinking, tool_use and the SDK's error classes. Swap it in from the test and script what Claude says.

Install

npm install --save-dev llmao

Mock the module

// Jest
jest.mock('@anthropic-ai/sdk', () => require('llmao/anthropic'));
// Vitest
vi.mock('@anthropic-ai/sdk', () => import('llmao/anthropic'));

import * as llmao from 'llmao/testing';
import { summarize } from './summarize'; // calls new Anthropic().messages.create()

beforeEach(() => llmao.reset());

test('summarizes', async () => {
  llmao.configure({ script: [{ when: 'Summarize', text: 'A short summary.' }] });

  expect(await summarize('A very long text')).toBe('A short summary.');
  expect(llmao.lastCall()).toMatchObject({ provider: 'anthropic', model: 'claude-sonnet-5' });
});

Tool use

llmao.configure({
  script: [
    { when: 'stock', toolCalls: [{ name: 'get_stock_price', args: { ticker: 'NVDA' } }] },
    { when: 'stock', afterToolResults: true, text: 'NVDA is trading at $1,337.' },
  ],
});

The first response has stop_reason: 'tool_use' and a tool_use block, exactly like the API. When your app sends the tool_result back, the second rule answers.

Errors

llmao.configure({ failures: { rateLimit: 1 } });
await expect(summarize('hi')).rejects.toBeInstanceOf(Anthropic.RateLimitError);

The error has status: 429, a retry-after header and the same body as the real API ({ type: 'error', error: { type: 'rate_limit_error' } }).

Related