Vitest 5.0.2, 비대칭 매처와 테스트 누수 탐지 오류 수정
Vitest의 9월 25일 패치가 객체 부분 비교와 비동기 누수 탐지의 오작동을 바로잡았다. Node 버전 조건부터 최소 테스트와 설정·복구까지 공식 문서로 따라간다.
자바스크립트 테스트 도구 Vitest가 2026년 9월 25일 08:58 UTC(한국시간 17:58)에 5.0.2를 공개했다. 이번 패치는 새 테스트 문법보다 기존 검사 결과의 신뢰성과 실행 안정성에 초점을 둔다. 특히 toMatchObject의 비대칭 매처 처리, 비동기 누수 탐지의 표준 입출력 핸들 처리, jsdom 28 이상에서의 Blob 요청 처리를 고쳤다. 9월 28일 기준 최근 48시간 소식은 아니므로 7일 범위의 공식 릴리스를 다룬다.
무엇이 달라졌나
공식 5.0.2 릴리스 노트에 따르면, expect(...).toMatchObject(...)에서 비대칭 매처를 함께 쓸 때의 오류가 수정됐다. 객체 전체가 정확히 같은지보다 특정 속성의 형태를 보려는 테스트에서 쓰는 조합이다. detect-async-leaks는 process.stdio 핸들을 무시하도록 바뀌었고, 보고서 생성의 동시 호출 처리 및 --silent를 쓰는 agent 리포터 동작도 수정됐다. jsdom 28 이상에서 Blob 본문을 가진 Request 처리, Set.prototype.add를 감시할 때의 스택 오버플로 수정도 릴리스 목록에 있다.
모든 테스트가 자동으로 빨라진다거나 전면적인 API 변경이 있다는 뜻은 아니다. 해당 조합을 쓰지 않는 프로젝트라면 체감 변화가 작을 수 있다. 반대로 최근 업데이트 뒤 비대칭 매처나 DOM 요청 테스트에서 실패가 생긴 팀에는 재현 테스트를 남기고 패치 버전을 비교해 볼 근거가 된다. 아래 명령과 코드는 2026년 9월 28일 확인한 공식 문서 기준 예시이며, 이 글을 위해 직접 실행하지 않았다.
설치 전 확인
공식 시작 안내는 Node.js 22.12.0 이상과 Vite 6.4.0 이상을 요구한다. 먼저 기존 프로젝트의 node --version, npm --version 및 package.json의 Vite·Vitest 버전을 확인한다. Node 버전이 낮다면 Vitest만 올리지 말고 런타임과 플러그인 호환성을 먼저 검토한다. 다음은 Node 조건을 만족하는 npm 기반 ESM 예제이며 Windows에서는 파일 생성 명령 대신 같은 내용을 편집기로 저장해도 된다. 기존 프로젝트에서 새 package.json을 덮어쓰지 않는다.
새 실습 폴더에서만 다음을 실행한다. 설치는 npm 레지스트리에서 의존성을 내려받고 해당 폴더의 package-lock.json과 node_modules를 만든다.
mkdir vitest-patch-demo
cd vitest-patch-demo
npm init -y
npm pkg set type=module
npm install --save-dev [email protected]
node --version
npm ls vitestnpm ls vitest 결과에 5.0.2가 표시되는지 확인한다. 기존 Vite 앱에서는 별도 폴더 생성 대신 해당 앱 디렉터리에서 설치하고 기존 잠금 파일·동료의 버전 정책을 먼저 확인한다. npm의 설치 실행은 네트워크 및 패키지에 대한 신뢰가 필요한 작업이다.
첫 테스트 만들기
프로젝트 루트에 price.js와 price.test.js를 아래처럼 각각 저장한다. 함수는 수량이 1 이상의 정수인지 검증하고 단가와 곱한다. 테스트 하나는 정상 결괏값을, 다른 하나는 오류의 일부 속성을 비대칭 매처로 확인한다. expect.any(String)는 오류의 전체 메시지를 고정하지 않는 예시이며, 이번 수정의 모든 내부 사례를 재현한다고 주장하지 않는다.
// price.js
export function total(unitPrice, quantity) {
if (!Number.isInteger(quantity) || quantity < 1) {
throw new RangeError('quantity must be a positive integer')
}
return unitPrice * quantity
}// price.test.js
import { expect, test } from 'vitest'
import { total } from './price.js'
test('three items have the expected total', () => {
expect(total(1200, 3)).toBe(3600)
})
test('invalid quantity exposes a useful error', () => {
let result
try {
total(1200, 0)
} catch (error) {
result = { name: error.name, message: error.message }
}
expect(result).toMatchObject({
name: 'RangeError',
message: expect.any(String),
})
})이제 아래 명령으로 1회 실행한다. 테스트 파일 이름에 .test. 또는 .spec.가 있어야 기본 검색 대상에 들어간다. 정상이라면 테스트 파일 1개와 테스트 2개가 통과했다고 표시된다. 실서비스 코드에서는 실패 시 message가 비어 있지 않은지까지 검증하는 편이 유용하다.
npx vitest runnpx는 로컬 실행 파일을 우선 찾지만 없으면 내려받을 수 있으므로 설치 성공과 npm ls vitest를 확인한 뒤 실행한다. 개발 중 자동 재실행은 npx vitest, CI의 한 번 실행은 npx vitest run을 쓴다. npm 스크립트를 선호하면 npm pkg set scripts.test='vitest run' 뒤 npm test를 실행해도 된다. npm 패키지 관리자와 셸 차이에 따라 인용부호 처리는 조정해야 한다.
설정과 결과 점검
Vitest는 기본적으로 기존 vite.config.*를 읽는다. 테스트 전용 vitest.config.*를 만들면 우선순위가 높고 기존 Vite 설정을 자동으로 합치지 않으므로, Vite 플러그인이나 별칭이 필요한 앱에서 무심코 분리하면 테스트의 모듈 해석이 바뀔 수 있다. 단독 실습에서 환경을 명시하고 싶다면 다음 vitest.config.js를 추가한다. Vite 앱이라면 기존 설정과 병합할지 먼저 판단한다.
// vitest.config.js
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: { environment: 'node' },
})브라우저 DOM이 필요한 테스트는 node 환경만으로 동작하지 않는다. 공식 문서에 따라 npm install -D jsdom으로 별도 패키지를 설치하고 environment: 'jsdom'으로 바꾼 다음, 사용 중인 jsdom·Node 버전의 호환성을 확인한다. 5.0.2의 Blob 수정은 jsdom 28 이상에 대한 릴리스 설명이며 모든 DOM 환경의 버그가 없어졌다는 보장은 아니다. 실패한 테스트의 파일명·스택·실제와 예상 값을 기록하고 npx vitest run price.test.js로 범위를 좁혀 비교한다.
권한과 되돌리기
로컬 테스트 자체가 외부 서비스 비용을 발생시키지는 않지만 npm 설치는 네트워크·디스크를 사용하며, 프로젝트의 테스트가 실제 API·파일·환경 변수에 접근한다면 그 권한과 데이터 경계는 테스트 코드에 달려 있다. 비밀값을 테스트 로그에 출력하지 않고, 실서비스 DB를 연결하지 않도록 격리한다. 저장소에 .vitest/ 같은 생성물을 무심코 커밋하지 않도록 공식 안내처럼 .gitignore를 살핀다.
기존 프로젝트에서 패치 후 문제가 생기면 잠금 파일과 변경 내역을 보고 직전 검증된 Vitest 버전으로 의존성을 복원한 뒤 테스트를 다시 실행한다. 이 실습 폴더만 만든 경우에는 필요한 결과를 백업한 뒤 그 폴더를 제거하면 된다. 기존 앱을 삭제하는 명령으로 실습 정리를 대신하지 않는다. 버전이 출력되지 않거나 npx가 임시 최신판을 실행했다면 npm ls vitest, Node 버전, 설치 로그와 잠금 파일을 순서대로 확인한다. 구체적 패치 수정의 적용 여부는 최소 재현 테스트를 두 버전에서 같은 조건으로 돌려 확인해야 한다.