SNA

Testing Mock API

Anthropic/OpenAI mock API、runOneshot、mock server type の使い方。

Testing Mock API

startMockAnthropicServer()

declare function startMockAnthropicServer(): Promise<MockServer>;
type MockServer = {
  port: number;
  server: http.Server;
  close: () => void;
  requests: Array<{ model: string; messages: unknown[]; stream: boolean; timestamp: string }>;
  onLog: (handler: (line: string) => void) => void;
};
type MockLogEntry = {
  ts: string;
  type: "request" | "response" | "error" | "info";
  method?: string;
  url?: string;
  model?: string;
  stream?: boolean;
  messageCount?: number;
  userText?: string;
  systemPromptLength?: number;
  replyText?: string;
  requestBody?: unknown;
  error?: string;
  message?: string;
};
import { startMockAnthropicServer } from "@sna-sdk/testing";

const mock = await startMockAnthropicServer();
process.env.ANTHROPIC_BASE_URL = `http://localhost:${mock.port}`;
process.env.ANTHROPIC_API_KEY = "sk-test";

mock.onLog((line) => {
  process.stdout.write(`${line}\n`);
});

try {
  // Anthropic-compatible API を期待する code を実行します。
} finally {
  mock.close();
}

動作:

  • OS が選んだ空き port で起動します。現在の実装は fixed port option を受け取りません。
  • Anthropic-compatible POST /v1/messages endpoint を提供します。
  • CORS preflight request をサポートします。
  • Parsed request を mock.requests に記録します。
  • mock.onLog から JSONL log line を emit します。
  • 通常 text には最後の user text を反転した文字列で応答します。Realistic な返答ではなく deterministic test fixture です。
  • Tool が宣言され、最新の user text に [tool:Name] が含まれる場合、その tool の tool_use block を返すか stream します。
  • Streaming SSE と non-streaming JSON response の両方をサポートします。

startMockOpenAIServer(options?)

declare function startMockOpenAIServer(options?: MockOpenAIOptions): Promise<MockOpenAIServer>;
type MockOpenAIOptions = {
  models?: Array<{ id: string; owned_by?: string }>;
  responseText?: string | ((ctx: MockOpenAIResponseContext) => string);
  chunkSize?: number;
};
import { startMockOpenAIServer } from "@sna-sdk/testing";

const mock = await startMockOpenAIServer({
  models: [{ id: "gpt-5.4", owned_by: "openai" }],
  responseText: ({ endpoint, userText }) => `${endpoint}: ${userText}`,
});

try {
  const res = await fetch(`${mock.url}/v1/responses`, {
    method: "POST",
    headers: { "Content-Type": "application/json", Authorization: "Bearer sk-test" },
    body: JSON.stringify({ model: "gpt-5.4", input: "hello" }),
  });
  console.log(await res.json());
  console.log(mock.requests[0]);
} finally {
  await mock.close();
}

動作:

  • 使用可能な local port で起動し、mock.url を公開します。
  • GET /v1/modelsPOST /v1/chat/completionsPOST /v1/responses を提供します。
  • authorization、model、stream flag、user text、system prompt length、raw request body を含む parsed request を記録します。
  • mock.onLog から JSONL log line を emit します。
  • Chat completions と responses の両方で non-streaming JSON と streaming SSE をサポートします。
  • デフォルトでは最後の user text を反転した文字列で応答します。固定応答や request ごとの応答は responseText で指定してください。

runOneshot(cliArgs?)

declare function runOneshot(cliArgs?: string[]): Promise<void>;

full interactive CLI harness を起動せず、mock Anthropic API に接続した Claude 実行だけを検証したい場合に使います。

runOneshot は mock server を起動し、ANTHROPIC_BASE_URL をその server に向け、渡された CLI argument で claude を実行します。stdout/stderr を capture し、Claude の exit code で process を終了します。CLAUDE_CONFIG_DIR には .sna/mock-claude-oneshot を使います。

Written files:

FileContents
.sna/mock-claude-stdout.logCaptured Claude stdout.
.sna/mock-claude-stderr.logCaptured Claude stderr.
.sna/mock-claude-oneshot/Temporary Claude config directory.

Instance helpers

generateInstanceName()

一意な test instance 名を作成します。並列 test で log/config directory の衝突を避けるために使います。

getInstancesDir() / getInstanceDir(name)

testing CLI が使う storage path を解決します。.sna/instances path を hard-code せず、この helper を優先してください。

listInstances()

disk に保存された test instance metadata を返します。debug UI や cleanup script に有用です。

readInstanceMeta(name) / writeInstanceMeta(name, meta)

test instance metadata を読み書きします。隔離された CLI run に追加 state を結び付ける場合に使います。

removeInstance(name)

instance directory と log を削除します。test cleanup で使います。

目次