codingstairs
노트에듀라이프연락
⌕검색⌘K
koen

Navigation

  • Intro
  • Blog
  • Life

연락하기

로그인 없이도 보낼 수 있어요. 답변이 필요하면 이메일을 함께 적어 주세요.

  • 익명 폼으로 의견 남기기 →
  • ✉ warragon112@gmail.com
  • 카카오톡 오픈채팅 ↗

© 2026 codingstairs

  • 노트
  • 에듀
  • 검색
  • 라이프
  • 연락
  • 약관
  • RSS
  • GitHub
에듀›테스트 전략과 품질 게이트›2단계

2단계

vitest 기본 + mock 패턴

0회 조회

vitest 기본 + mock 패턴

Jest 의 후계로 자리잡은 vitest. Vite 와 네이티브 호환 + ESM 우선 + 빠름.

1. 설치

pnpm add -D vitest @vitest/ui

package.json 스크립트:

{ "scripts": { "test": "vitest run", "test:watch": "vitest" } }

2. 첫 테스트

// src/lib/format.test.ts
import { describe, it, expect } from "vitest";
import { formatDate } from "./format";

describe("formatDate", () => {
  it("YYYY-MM-DD 형식", () => {
    expect(formatDate(new Date("2026-05-06"))).toBe("2026-05-06");
  });
});

3. 환경 — node vs jsdom

// vitest.config.ts
export default defineConfig({
  test: {
    environment: "node",              // DOM 미사용 기본
    globals: true,                    // describe/it/expect 전역
  },
});

DOM · window 를 쓰는 코드는 environment: "jsdom". 파일 단위 오버라이드:

// @vitest-environment jsdom

4. vi.hoisted — mock 순서 문제 해결

import { vi, describe, it, expect } from "vitest";

const { mockQuery } = vi.hoisted(() => ({ mockQuery: vi.fn() }));
vi.mock("@/shared/lib/db", () => ({ pool: { query: mockQuery } }));

// 이제 import 한 코드가 이 mock 을 사용
import { getUserById } from "./user-repo";

describe("getUserById", () => {
  it("쿼리 결과 반환", async () => {
    mockQuery.mockResolvedValueOnce({ rows: [{ id: 1 }] });
    expect(await getUserById(1)).toEqual({ id: 1 });
  });
});

vi.mock 은 호이스팅되지만 변수 참조가 불가능. vi.hoisted 로 mock 생성도 함께 호이스팅.

5. 환경변수 · 전역 stub

import { beforeEach, afterEach } from "vitest";

beforeEach(() => {
  vi.stubEnv("REVALIDATE_URL", "http://localhost:3000");
  vi.resetModules();
});

afterEach(() => {
  vi.unstubAllEnvs();
  vi.unstubAllGlobals();
});

it("fetch 호출", async () => {
  const fetchMock = vi.fn().mockResolvedValue({ ok: true, status: 200 });
  vi.stubGlobal("fetch", fetchMock);
  await triggerRevalidate();
  expect(fetchMock).toHaveBeenCalled();
});

resetModules + stubEnv 조합으로 환경변수 분기 테스트.

6. React 컴포넌트 — testing-library

pnpm add -D @testing-library/react @testing-library/jest-dom
// @vitest-environment jsdom
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";

it("클릭 시 증가", async () => {
  render(<Counter />);
  await userEvent.click(screen.getByRole("button", { name: /increment/i }));
  expect(screen.getByText("1")).toBeInTheDocument();
});

7. snapshot — 신중히

expect(user).toMatchSnapshot();

편하지만 남용하면 "스냅샷 덩어리" 가 됨. 복잡한 출력만 선별적으로.

8. coverage

pnpm add -D @vitest/coverage-v8
vitest run --coverage

vitest.config.ts:

test: {
  coverage: {
    provider: "v8",
    exclude: ["**/*.test.ts", "**/dist/**"],
    thresholds: { lines: 70, functions: 70, branches: 70 },
  },
}

9. 자주 걸리는 자리

  • vi.mock 변수 참조 에러 — vi.hoisted 사용
  • afterEach 정리 누락 — env stub 남아 다른 테스트 오염
  • jsdom 에서 window 없음 — environment: "jsdom" 지정
  • snapshot 오래되면 의미 없음 — vitest -u 로 주기적 갱신 + 리뷰

하고픈 말

vi.hoisted + stubEnv + stubGlobal 셋만 확실히 잡으면 사실상 모든 모킹 상황에 대응 가능합니다.

Next

  • 03-pytest-fixtures

← 1단계

테스트 피라미드 · 트레이드오프

3단계 →

pytest · fixture · parametrize