Geuni

단위테스트: 파일시스템(file-system) 테스트

파일시스템의 유닛테스트는 어떻게 작성할 수 있을까?

예시

vitest기준으로 공식문서에서는 다음과 같이 소스코드를 제공해준다.
하지만 테스트코드를 실행해보면 에러가 발생한다.

// real-hello-world.js
import { readFileSync } from "node:fs";

export function readHelloWorld(path) {
  return readFileSync(path, "utf-8");
}
// hello-world.test.js
import { beforeEach, expect, it, vi } from "vitest";
import { fs, vol } from "memfs";
import { readHelloWorld } from "./read-hello-world.js";

// tell vitest to use fs mock from __mocks__ folder
// this can be done in a setup file if fs should always be mocked
vi.mock("node:fs");
vi.mock("node:fs/promises");

beforeEach(() => {
  // reset the state of in-memory fs
  vol.reset();
});

it("should return correct text", () => {
  const path = "/hello-world.txt";
  fs.writeFileSync(path, "hello world");

  const text = readHelloWorld(path);
  expect(text).toBe("hello world");
});

it("can return a value multiple times", () => {
  // you can use vol.fromJSON to define several files
  vol.fromJSON(
    {
      "./dir1/hw.txt": "hello dir1",
      "./dir2/hw.txt": "hello dir2",
    },
    // default cwd
    "/tmp"
  );

  expect(readHelloWorld("/tmp/dir1/hw.txt")).toBe("hello dir1");
  expect(readHelloWorld("/tmp/dir2/hw.txt")).toBe("hello dir2");
});


에러를 해결하기 위해 내게 효과가 있었던 방법은 아래와 같다.

vi.mock("node:fs", async () => {
  const memfs = await vi.importActual("memfs");

  return {
    default: memfs.fs,
    ...memfs.fs,
  };
});

이 방법은 react-router-dom을 모킹할 때 방법과 동일하다.


memfs

위 코드에서 다시 확인해보면 memfs가 보인다. 이게 뭘까?
노드에서 fs는 import 종류가 다양하다.

import fs from "fs"; // Node.js 기본 파일시스템 모듈 (동기/콜백 방식)
import fs from "node:fs"; // 위와 동일하지만 Node.js 내장 모듈임을 명시 (권장)
import fsPromise from "fs/promises"; // Promise 기반 비동기 파일시스템 (async/await 사용)
import { fs } from "memfs"; // 메모리 기반 가상 파일시스템 (테스트용, 실제 파일 생성 안함)

memfs는 파일시스템을 테스트하기 위해 제공하는 라이브러리이다.
파일시스템을 테스트하기 위해선 실제 파일에 영향이 간다.

예를들어 파일을 읽은 후 파일의 내용을 수정한다고 가정했을 때, 테스트코드를 실행할 때마다 실 개발환경에 영향을 주는 것이다.

이 문제를 해결하기 위해 memfs를 사용한다.
즉 격리된 테스트환경을 제공해주는 라이브러리이다.


참고자료

vitest docs: file-system
github: memfs
#384 mock-fs issue:mock-fs to memfs

단위테스트: 파일시스템(file-system) 테스트 | geuni