블로그 목록
AI

Vercel AI SDK 테스트하기 — MockLanguageModelV2로 토큰 안 태우고 LLM 코드 검증하기

AI 기능을 붙이고 나서 테스트를 짜려다 막혔다. generateText를 감싼 내 함수를 테스트하려면 결국 실제 모델을 불러야 하는데, 그러면 테스트 한 번 돌릴 때마다 토큰을 태운다. 게다가 모델 응답이 매번 달라지니 expect로 결과를 못 박을 수가 없다. CI에서 돌리려면 API 키까지 넣어야 하고.

문제는 "모델을 호출한다"는 사실이 아니라 "응답을 받은 뒤 내 코드가 뭘 하는가"를 검증하고 싶다는 거다. 그렇다면 모델 자리에 가짜를 끼우면 된다. Vercel AI SDK는 ai/test로 MockLanguageModelV2를 제공한다.

generateText 모킹

doGenerate에 내가 원하는 응답을 그대로 반환하게 하면, 네트워크 없이 함수가 돈다.

// summarize.test.ts
import { generateText } from 'ai';
import { MockLanguageModelV2 } from 'ai/test';
import { expect, test } from 'vitest';

test('요약 결과 앞뒤 공백을 다듬는다', async () => {
  const model = new MockLanguageModelV2({
    doGenerate: async () => ({
      finishReason: 'stop',
      usage: { inputTokens: 10, outputTokens: 20, totalTokens: 30 },
      content: [{ type: 'text', text: '  세 줄 요약  ' }],
      warnings: [],
    }),
  });

  const { text } = await generateText({ model, prompt: '아무거나' });
  expect(text.trim()).toBe('세 줄 요약');
});

응답이 고정이니 결과도 고정이다. 토큰 0, API 키 불필요.

스트리밍 모킹

스트리밍은 simulateReadableStream으로 청크를 하나씩 흘려보낸다. 실제 모델이 토큰을 쪼개 보내는 상황을 그대로 재현할 수 있다.

import { streamText, simulateReadableStream } from 'ai';
import { MockLanguageModelV2 } from 'ai/test';

const model = new MockLanguageModelV2({
  doStream: async () => ({
    stream: simulateReadableStream({
      chunkDelayInMs: 10,
      chunks: [
        { type: 'text-start', id: '1' },
        { type: 'text-delta', id: '1', delta: '안녕' },
        { type: 'text-delta', id: '1', delta: '하세요' },
        { type: 'text-end', id: '1' },
        {
          type: 'finish',
          finishReason: 'stop',
          usage: { inputTokens: 3, outputTokens: 5, totalTokens: 8 },
        },
      ],
    }),
  }),
});

const result = streamText({ model, prompt: '인사해줘' });
expect(await result.text).toBe('안녕하세요');

chunkDelayInMs를 주면 딜레이까지 흉내 내니, 스트리밍 중간에 멈추거나 로딩 UI를 보여주는 로직도 검증할 수 있다.


핵심은 테스트가 모델의 답을 평가하는 게 아니라 내 코드의 동작을 평가하게 만드는 거다. 응답을 고정해두면 파싱·후처리·에러 분기 같은 내 로직을 결정론적으로 찍어볼 수 있다. 실제 모델 품질 확인은 별도의 평가(eval) 단계로 떼어내고, 단위 테스트는 가짜 모델로 빠르고 공짜로 돌리자.