Skip to content
Vitest 1
Main Navigation 가이드API구성고급
1.6.1
0.34.6

한국어

English
简体中文
繁體中文
Español
Français
Русский
Português – Brasil
Deutsch
日本語
Italiano
Polski
Türkçe
čeština
magyar

한국어

English
简体中文
繁體中文
Español
Français
Русский
Português – Brasil
Deutsch
日本語
Italiano
Polski
Türkçe
čeština
magyar

외관

Sidebar Navigation

가이드

Vitest를 선택하는 이유

시작하기

기능

워크스페이스

명령줄 인터페이스

테스트 필터링

리포터

커버리지

스냅샷

모의화

타입 테스트

Vitest UI

브라우저 모드

소스 내 테스트

테스트 컨텍스트

테스트 환경

Matcher 확장하기

IDE 통합

디버깅

다른 테스트 러너와의 비교

마이그레이션 가이드

일반적인 오류

성능 향상

API

테스트 API 참조

Mock 함수

Vi

expect

expectTypeOf

assert

assertType

구성

Vitest 구성 파일 관리

Vitest 구성하기

이 페이지에서

expect ​

아래 타입은 아래 타입 정의에서 사용됩니다.

ts
type Awaitable<T> = T | PromiseLike<T>;

expect는 어설션을 생성하는 데 사용됩니다. 여기서 어설션(assertion)은 특정 조건이 참인지 확인하는 함수를 호출하는 것을 의미합니다. Vitest는 기본적으로 chai 어설션을 제공하며, chai를 기반으로 구축된 Jest 호환 어설션도 제공합니다.

예를 들어, 다음 코드는 input 값이 2와 같은지 단언합니다. 그렇지 않으면 어설션이 오류를 발생시키고 테스트가 실패합니다.

ts
import { expect } from 'vitest';

const input = Math.sqrt(4);

expect(input).to.equal(2); // chai API
expect(input).toBe(2); // jest API

정확히 말하면, 이 예제는 test 함수를 사용하지 않으므로 콘솔에 Vitest 출력이 아닌 Node.js 오류가 표시됩니다. test에 대해 자세히 알아보려면 테스트 API 참조를 확인하세요.

또한 expect는 매처 함수 등에 접근하기 위해 정적으로 사용할 수도 있습니다.

WARNING

expect는 표현식에 타입 오류가 없을 경우 타입 테스트에 영향을 주지 않습니다. Vitest를 타입 검사기로 사용하려면 expectTypeOf 또는 assertType을 사용하세요.

soft ​

  • 타입: ExpectStatic & (actual: any) => Assertions

expect.soft는 expect와 유사하게 동작하지만, 실패한 어설션이 발생하더라도 테스트 실행을 중단하지 않고 계속 진행하며, 해당 실패를 테스트 실패로 기록합니다. 테스트 중에 발생한 모든 오류는 테스트가 완료될 때 출력됩니다.

ts
import { expect, test } from 'vitest';

test('expect.soft 테스트', () => {
  expect.soft(1 + 1).toBe(3); // 테스트를 실패로 표시하고 계속 진행
  expect.soft(1 + 2).toBe(4); // 테스트를 실패로 표시하고 계속 진행
});
// 테스트가 끝나면 위의 오류들이 출력됩니다.

expect와 함께 사용할 수 있습니다. expect 어설션이 실패하면 테스트가 즉시 종료되고 모든 오류가 표시됩니다.

ts
import { expect, test } from 'vitest';

test('expect.soft 테스트', () => {
  expect.soft(1 + 1).toBe(3); // 테스트를 실패로 표시하고 계속 진행
  expect(1 + 2).toBe(4); // 실패하고 테스트를 종료하며, 이전의 모든 오류가 출력됩니다.
  expect.soft(1 + 3).toBe(5); // 실행되지 않음
});

WARNING

expect.soft는 test 함수 내에서만 사용할 수 있습니다.

not ​

not을 사용하면 어설션의 결과를 부정할 수 있습니다. 예를 들어, 다음 코드는 input 값이 2와 같지 않음을 단언합니다. 만약 같다면 어설션이 오류를 발생시키고 테스트가 실패합니다.

ts
import { expect, test } from 'vitest';

const input = Math.sqrt(16);

expect(input).not.to.equal(2); // chai API
expect(input).not.toBe(2); // jest API

toBe ​

  • 타입: (value: any) => Awaitable<void>

toBe는 원시 타입의 값이 같은지, 또는 객체가 동일한 메모리 주소를 참조하는지 확인할 때 사용합니다. 이는 expect(Object.is(3, 3)).toBe(true)를 호출하는 것과 같습니다. 객체가 동일하지 않지만 구조가 같은지 확인하려면 toEqual을 사용하세요.

예를 들어, 다음 코드는 거래자가 사과 13개를 가지고 있는지 확인합니다.

ts
import { expect, test } from 'vitest';

const stock = {
  type: 'apples',
  count: 13,
};

test('stock has 13 apples', () => {
  expect(stock.type).toBe('apples');
  expect(stock.count).toBe(13);
});

test('stocks are the same', () => {
  const refStock = stock; // same reference

  expect(stock).toBe(refStock);
});

부동 소수점 숫자와 함께 toBe를 사용하는 것은 권장되지 않습니다. JavaScript는 숫자를 반올림하므로 0.1 + 0.2는 정확히 0.3이 아닙니다. 부동 소수점 숫자를 안정적으로 단언하려면 toBeCloseTo 어설션을 사용하세요.

toBeCloseTo ​

  • 타입: (value: number, numDigits?: number) => Awaitable<void>

toBeCloseTo를 사용하여 부동 소수점 숫자를 비교할 수 있습니다. 선택적 인수인 numDigits는 소수점 이하 몇 자리까지 비교할지 지정합니다. 예를 들어:

ts
import { expect, test } from 'vitest';

test.fails('decimals are not equal in javascript', () => {
  expect(0.2 + 0.1).toBe(0.3); // 0.2 + 0.1은 0.30000000000000004입니다.
});

test('decimals are rounded to 5 after the point', () => {
  // 0.2 + 0.1은 0.30000 | "000000000004"가 제거되었습니다.
  expect(0.2 + 0.1).toBeCloseTo(0.3, 5);
  // 0.30000000000000004에서 제거된 것은 없습니다.
  expect(0.2 + 0.1).not.toBeCloseTo(0.3, 50);
});

toBeDefined ​

  • 타입: () => Awaitable<void>

toBeDefined는 값이 undefined가 아님을 단언합니다. 함수가 어떤 값이든 반환했는지 확인하는 데 유용합니다.

ts
import { expect, test } from 'vitest';

function getApples() {
  return 3;
}

test('function returned something', () => {
  expect(getApples()).toBeDefined();
});

toBeUndefined ​

  • 타입: () => Awaitable<void>

toBeUndefined는 toBeDefined와 반대로, 값이 undefined인지 확인합니다. 함수가 아무것도 반환하지 않았는지 확인하는 데 유용합니다.

ts
import { expect, test } from 'vitest';

function getApplesFromStock(stock: string) {
  if (stock === 'Bill') return 13;
}

test("mary doesn't have a stock", () => {
  expect(getApplesFromStock('Mary')).toBeUndefined();
});

toBeTruthy ​

  • 타입: () => Awaitable<void>

toBeTruthy는 값이 불리언으로 변환될 때 true인지 단언합니다. 값 자체보다는 true로 평가되는지 확인할 때 유용합니다.

예를 들어, 다음 코드가 있을 때 stocks.getInfo의 반환 값에는 관심이 없습니다. 복잡한 객체, 문자열 또는 다른 어떤 것이든 될 수 있습니다. 코드는 여전히 작동합니다.

ts
import { Stocks } from './stocks.js';

const stocks = new Stocks();
stocks.sync('Bill');
if (stocks.getInfo('Bill')) stocks.sell('apples', 'Bill');

따라서 stocks.getInfo가 truthy인지 테스트하려면 다음과 같이 작성할 수 있습니다.

ts
import { expect, test } from 'vitest';
import { Stocks } from './stocks.js';

const stocks = new Stocks();

test('if we know Bill stock, sell apples to him', () => {
  stocks.sync('Bill');
  expect(stocks.getInfo('Bill')).toBeTruthy();
});

JavaScript의 모든 값은 false, null, undefined, NaN, 0, -0, 0n, "" 및 document.all을 제외하고는 truthy입니다.

toBeFalsy ​

  • 타입: () => Awaitable<void>

toBeFalsy는 값이 불리언으로 변환될 때 false인지 단언합니다. 값 자체보다는 false로 평가되는지 확인할 때 유용합니다.

예를 들어, 다음 코드가 있을 때 stocks.stockFailed의 반환 값에는 관심이 없습니다. falsy 값을 반환할 수 있지만 코드는 여전히 실행됩니다.

ts
import { Stocks } from './stocks.js';

const stocks = new Stocks();
stocks.sync('Bill');
if (!stocks.stockFailed('Bill')) stocks.sell('apples', 'Bill');

따라서 stocks.stockFailed가 falsy인지 테스트하려면 다음과 같이 작성할 수 있습니다.

ts
import { expect, test } from 'vitest';
import { Stocks } from './stocks.js';

const stocks = new Stocks();

test("if Bill stock hasn't failed, sell apples to him", () => {
  stocks.syncStocks('Bill');
  expect(stocks.stockFailed('Bill')).toBeFalsy();
});

JavaScript의 모든 값은 false, null, undefined, NaN, 0, -0, 0n, "" 및 document.all을 제외하고는 truthy입니다.

toBeNull ​

  • 타입: () => Awaitable<void>

toBeNull은 단순히 어떤 값이 null인지 단언합니다. .toBe(null)의 별칭입니다.

ts
import { expect, test } from 'vitest';

function apples() {
  return null;
}

test("we don't have apples", () => {
  expect(apples()).toBeNull();
});

toBeNaN ​

  • 타입: () => Awaitable<void>

toBeNaN은 단순히 어떤 값이 NaN인지 단언합니다. .toBe(NaN)의 별칭입니다.

ts
import { expect, test } from 'vitest';

let i = 0;

function getApplesCount() {
  i++;
  return i > 1 ? Number.NaN : i;
}

test('getApplesCount has some unusual side effects...', () => {
  expect(getApplesCount()).not.toBeNaN();
  expect(getApplesCount()).toBeNaN();
});

toBeTypeOf ​

  • 타입: (c: 'bigint' | 'boolean' | 'function' | 'number' | 'object' | 'string' | 'symbol' | 'undefined') => Awaitable<void>

toBeTypeOf는 실제 값이 주어진 타입과 같은 타입인지 단언합니다.

ts
import { expect, test } from 'vitest';

const actual = 'stock';

test('stock is type of string', () => {
  expect(actual).toBeTypeOf('string');
});

toBeInstanceOf ​

  • 타입: (c: any) => Awaitable<void>

toBeInstanceOf는 실제 값이 주어진 클래스의 인스턴스인지 단언합니다.

ts
import { expect, test } from 'vitest';
import { Stocks } from './stocks.js';

const stocks = new Stocks();

test('stocks are instance of Stocks', () => {
  expect(stocks).toBeInstanceOf(Stocks);
});

toBeGreaterThan ​

  • 타입: (n: number | bigint) => Awaitable<void>

toBeGreaterThan은 실제 값이 주어진 값보다 큰지 단언합니다. 값이 같으면 테스트는 실패합니다.

ts
import { expect, test } from 'vitest';
import { getApples } from './stocks.js';

test('have more then 10 apples', () => {
  expect(getApples()).toBeGreaterThan(10);
});

toBeGreaterThanOrEqual ​

  • 타입: (n: number | bigint) => Awaitable<void>

toBeGreaterThanOrEqual은 실제 값이 주어진 값보다 크거나 같은지 단언합니다.

ts
import { expect, test } from 'vitest';
import { getApples } from './stocks.js';

test('have 11 apples or more', () => {
  expect(getApples()).toBeGreaterThanOrEqual(11);
});

toBeLessThan ​

  • 타입: (n: number | bigint) => Awaitable<void>

toBeLessThan은 실제 값이 주어진 값보다 작은지 단언합니다. 값이 같으면 테스트는 실패합니다.

ts
import { expect, test } from 'vitest';
import { getApples } from './stocks.js';

test('have less then 20 apples', () => {
  expect(getApples()).toBeLessThan(20);
});

toBeLessThanOrEqual ​

  • 타입: (n: number | bigint) => Awaitable<void>

toBeLessThanOrEqual은 실제 값이 주어진 값보다 작거나 같은지 단언합니다.

ts
import { expect, test } from 'vitest';
import { getApples } from './stocks.js';

test('have 11 apples or less', () => {
  expect(getApples()).toBeLessThanOrEqual(11);
});

toEqual ​

  • 타입: (received: any) => Awaitable<void>

toEqual은 실제 값이 주어진 값과 같거나 객체인 경우, 재귀적으로 비교하여 동일한 구조를 갖는지 단언합니다. 다음 예제에서 toEqual과 toBe의 차이점을 확인할 수 있습니다.

ts
import { expect, test } from 'vitest';

const stockBill = {
  type: 'apples',
  count: 13,
};

const stockMary = {
  type: 'apples',
  count: 13,
};

test('stocks have the same properties', () => {
  expect(stockBill).toEqual(stockMary);
});

test('stocks are not the same', () => {
  expect(stockBill).not.toBe(stockMary);
});

WARNING

Error 객체에 대해서는 깊은 동일성 비교가 수행되지 않습니다. Error의 message 속성만이 동일성 비교 대상이 됩니다. message 이외의 속성을 확인하기 위해 동일성을 사용자 정의하려면 expect.addEqualityTesters를 사용하십시오. 무엇인가가 예외를 던졌는지 테스트하려면 toThrowError 어설션을 사용하십시오.

toStrictEqual ​

  • 타입: (received: any) => Awaitable<void>

toStrictEqual은 실제 값이 주어진 값과 같거나 객체인 경우, 동일한 구조를 갖는지 (재귀적으로 비교) 그리고 동일한 타입인지 단언합니다.

.toEqual과의 차이점:

  • undefined 속성이 있는 키를 확인합니다. 예를 들어 .toStrictEqual을 사용할 때 {a: undefined, b: 2}는 {b: 2}와 일치하지 않습니다.
  • 배열의 빈 요소를 확인합니다. 예를 들어 .toStrictEqual을 사용할 때 [, 1]은 [undefined, 1]과 일치하지 않습니다.
  • 객체의 타입이 동일한지 확인합니다. 예를 들어 필드 a와 b가 있는 클래스 인스턴스는 필드 a와 b가 있는 리터럴 객체와 같지 않습니다.
ts
import { expect, test } from 'vitest';

class Stock {
  constructor(type) {
    this.type = type;
  }
}

test('structurally the same, but semantically different', () => {
  expect(new Stock('apples')).toEqual({ type: 'apples' });
  expect(new Stock('apples')).not.toStrictEqual({ type: 'apples' });
});

toContain ​

  • 타입: (received: string) => Awaitable<void>

toContain은 실제 값이 배열에 포함되어 있는지 어설션합니다. toContain은 또한 문자열이 다른 문자열의 부분 문자열인지 확인할 수도 있습니다. Vitest 1.0 이후, 브라우저와 유사한 환경에서 테스트를 실행하는 경우, 이 어설션은 클래스가 classList에 포함되어 있는지, 또는 요소가 다른 요소 내부에 있는지 확인할 수도 있습니다.

ts
import { expect, test } from 'vitest';
import { getAllFruits } from './stocks.js';

test('the fruit list contains orange', () => {
  expect(getAllFruits()).toContain('orange');

  const element = document.querySelector('#el');
  // element has a class
  expect(element.classList).toContain('flex');
  // element is inside another one
  expect(document.querySelector('#wrapper')).toContain(element);
});

toContainEqual ​

  • 타입: (received: any) => Awaitable<void>

toContainEqual은 배열에 특정 구조와 값을 가진 요소가 포함되어 있는지 확인합니다. 배열의 각 요소에 대해 toEqual을 적용하는 것과 같습니다.

ts
import { expect, test } from 'vitest';
import { getFruitStock } from './stocks.js';

test('apple available', () => {
  expect(getFruitStock()).toContainEqual({ fruit: 'apple', count: 5 });
});

toHaveLength ​

  • 타입: (received: number) => Awaitable<void>

toHaveLength는 객체가 .length 속성을 가지고 있고, 그 값이 특정 숫자인지 확인합니다.

ts
import { expect, test } from 'vitest';

test('toHaveLength', () => {
  expect('abc').toHaveLength(3);
  expect([1, 2, 3]).toHaveLength(3);

  expect('').not.toHaveLength(3); // .length가 3이 아님
  expect({ length: 3 }).toHaveLength(3);
});

toHaveProperty ​

  • 타입: (key: any, received?: any) => Awaitable<void>

toHaveProperty는 객체가 주어진 key에 해당하는 속성을 가지고 있는지 확인합니다.

선택적으로 값 매개변수를 제공하여 속성 값에 대한 깊은 동일성(deep equality) 비교를 수행할 수 있습니다. 이는 toEqual 매처와 유사하게, 객체의 해당 속성 값과 비교하는 데 사용됩니다.

ts
import { expect, test } from 'vitest';

const invoice = {
  isActive: true,
  'P.O': '12345',
  customer: {
    first_name: 'John',
    last_name: 'Doe',
    location: 'China',
  },
  total_amount: 5000,
  items: [
    {
      type: 'apples',
      quantity: 10,
    },
    {
      type: 'oranges',
      quantity: 5,
    },
  ],
};

test('John Doe 인보이스', () => {
  expect(invoice).toHaveProperty('isActive'); // 키의 존재 여부를 확인합니다.
  expect(invoice).toHaveProperty('total_amount', 5000); // 키가 존재하고 값이 일치하는지 확인합니다.

  expect(invoice).not.toHaveProperty('account'); // 해당 키가 존재하지 않는지 확인합니다.

  // 점 표기법을 사용한 깊은 접근
  expect(invoice).toHaveProperty('customer.first_name');
  expect(invoice).toHaveProperty('customer.last_name', 'Doe');
  expect(invoice).not.toHaveProperty('customer.location', 'India');

  // 키를 포함하는 배열을 사용한 깊은 접근
  expect(invoice).toHaveProperty('items[0].type', 'apples');
  expect(invoice).toHaveProperty('items.0.type', 'apples'); // 점 표기법도 작동합니다.

  // keyPath를 포함하는 배열을 사용한 깊은 접근
  expect(invoice).toHaveProperty(['items', 0, 'type'], 'apples');
  expect(invoice).toHaveProperty(['items', '0', 'type'], 'apples'); // 문자열 표기법도 작동합니다.

  // 키가 깊은 접근으로 해석되는 것을 방지하려면 키를 배열로 감싸세요.
  expect(invoice).toHaveProperty(['P.O'], '12345');
});

toMatch ​

  • 타입: (received: string | regexp) => Awaitable<void>

toMatch는 문자열이 정규 표현식 또는 문자열과 일치하는지 확인합니다.

ts
import { expect, test } from 'vitest';

test('인기 과일', () => {
  expect('top fruits include apple, orange and grape').toMatch(/apple/);
  expect('applefruits').toMatch('fruit'); // toMatch는 문자열도 사용할 수 있습니다.
});

toMatchObject ​

  • 타입: (received: object | array) => Awaitable<void>

toMatchObject는 객체가 다른 객체의 속성 부분 집합과 일치하는지 확인합니다. 즉, received 객체가 주어진 객체의 속성을 포함하는지 확인합니다.

객체 배열을 전달할 수도 있습니다. 이는 arrayContaining이 수신된 배열에 추가 요소가 있어도 통과하는 것과 달리, 두 배열의 요소 개수가 정확히 일치하는지 확인할 때 유용합니다.

ts
import { expect, test } from 'vitest';

const johnInvoice = {
  isActive: true,
  customer: {
    first_name: 'John',
    last_name: 'Doe',
    location: 'China',
  },
  total_amount: 5000,
  items: [
    {
      type: 'apples',
      quantity: 10,
    },
    {
      type: 'oranges',
      quantity: 5,
    },
  ],
};

const johnDetails = {
  customer: {
    first_name: 'John',
    last_name: 'Doe',
    location: 'China',
  },
};

test('송장에 John의 개인 정보가 있는지 확인', () => {
  expect(johnInvoice).toMatchObject(johnDetails);
});

test('요소 개수가 정확히 일치해야 함을 확인', () => {
  // 객체 배열이 일치하는지 확인합니다.
  expect([{ foo: 'bar' }, { baz: 1 }]).toMatchObject([
    { foo: 'bar' },
    { baz: 1 },
  ]);
});

toThrowError ​

  • 타입: (received: any) => Awaitable<void>

  • 별칭: toThrow

toThrowError는 함수를 호출했을 때 오류가 발생하는지 확인합니다.

특정 오류가 발생하는지 확인하기 위해 선택적 인수를 제공할 수 있습니다.

  • 정규 표현식: 오류 메시지가 주어진 패턴과 일치하는지 확인합니다.
  • 문자열: 오류 메시지에 주어진 문자열이 포함되어 있는지 확인합니다.

TIP

오류를 catch하려면 테스트하려는 코드를 함수로 감싸야 합니다. 그렇지 않으면 테스트가 실패합니다.

예를 들어 getFruitStock('pineapples') 함수가 오류를 발생시키는지 테스트하려면 다음과 같이 작성할 수 있습니다.

ts
import { expect, test } from 'vitest';

function getFruitStock(type: string) {
  if (type === 'pineapples') throw new Error('Pineapples are not in stock');

  // 다른 작업 수행
}

test('파인애플 처리 시 오류 발생', () => {
  // 오류 메시지에 "stock"가 포함되어 있는지 테스트합니다. 다음은 동일합니다.
  expect(() => getFruitStock('pineapples')).toThrowError(/stock/);
  expect(() => getFruitStock('pineapples')).toThrowError('stock');

  // 정확한 오류 메시지 테스트
  expect(() => getFruitStock('pineapples')).toThrowError(
    /^Pineapples are not in stock$/
  );
});

TIP

비동기 함수의 오류 발생 여부를 테스트하려면 rejects와 함께 사용하세요.

js
function getAsyncFruitStock() {
  return Promise.reject(new Error('empty'));
}

test('파인애플 처리 시 오류 발생', async () => {
  await expect(() => getAsyncFruitStock()).rejects.toThrowError('empty');
});

toMatchSnapshot ​

  • 타입: <T>(shape?: Partial<T> | string, message?: string) => void

이 매처는 값이 최신 스냅샷과 일치하는지 확인합니다.

테스트 이름에 추가되는 선택적 hint 문자열 인수를 제공할 수 있습니다. Vitest는 스냅샷 이름 끝에 항상 숫자를 추가하지만, 짧고 설명적인 힌트를 사용하면 하나의 it 또는 test 블록 내에서 여러 스냅샷을 숫자보다 효과적으로 구별할 수 있습니다. Vitest는 해당 .snap 파일에서 이름별로 스냅샷을 정렬합니다.

TIP

스냅샷이 일치하지 않아 테스트가 실패하는 경우, 예상되는 불일치라면 u 키를 눌러 스냅샷을 업데이트할 수 있습니다. 또는 -u 또는 --update CLI 옵션을 전달하여 Vitest가 항상 테스트를 업데이트하도록 설정할 수 있습니다.

ts
import { expect, test } from 'vitest';

test('스냅샷과 일치', () => {
  const data = { foo: new Set(['bar', 'snapshot']) };
  expect(data).toMatchSnapshot();
});

객체의 구조만 테스트하고 완전한 일치가 필요하지 않은 경우 객체의 모양(shape)을 제공할 수도 있습니다.

ts
import { expect, test } from 'vitest';

test('스냅샷과 일치', () => {
  const data = { foo: new Set(['bar', 'snapshot']) };
  expect(data).toMatchSnapshot({ foo: expect.any(Set) });
});

toMatchInlineSnapshot ​

  • 타입: <T>(shape?: Partial<T> | string, snapshot?: string, message?: string) => void

이 매처는 값이 최신 인라인 스냅샷과 일치하는지 확인합니다.

Vitest는 외부 .snap 파일 대신 테스트 파일 내의 매처에 inlineSnapshot 문자열 인수를 추가하고 업데이트합니다.

ts
import { expect, test } from 'vitest';

test('인라인 스냅샷과 일치', () => {
  const data = { foo: new Set(['bar', 'snapshot']) };
  // Vitest는 스냅샷을 업데이트할 때 다음 내용을 업데이트합니다.
  expect(data).toMatchInlineSnapshot(`
    {
      "foo": Set {
        "bar",
        "snapshot",
      },
    }
  `);
});

객체의 구조만 테스트하고 완전한 일치가 필요하지 않은 경우 객체의 모양(shape)을 제공할 수도 있습니다.

ts
import { expect, test } from 'vitest';

test('스냅샷과 일치', () => {
  const data = { foo: new Set(['bar', 'snapshot']) };
  expect(data).toMatchInlineSnapshot(
    { foo: expect.any(Set) },
    `
    {
      "foo": Any<Set>,
    }
  `
  );
});

toMatchFileSnapshot 0.30.0+ ​

  • 타입: <T>(filepath: string, message?: string) => Promise<void>

스냅샷을 .snap 파일 대신, 사용자가 명시적으로 지정한 파일의 내용과 비교하거나 업데이트합니다.

ts
import { expect, it } from 'vitest';

it('기본 렌더링', async () => {
  const result = renderHTML(h('div', { class: 'foo' }));
  await expect(result).toMatchFileSnapshot('./test/basic.output.html');
});

파일 시스템 작업은 비동기적으로 수행되므로 toMatchFileSnapshot()와 함께 await를 사용해야 합니다.

toThrowErrorMatchingSnapshot ​

  • 타입: (message?: string) => void

toMatchSnapshot과 동일한 방식으로 작동하지만, toThrowError 매처와 함께 사용하기 위해 오류 값을 예상합니다.

toThrowErrorMatchingInlineSnapshot ​

  • 타입: (snapshot?: string, message?: string) => void

toMatchInlineSnapshot과 동일한 방식으로 작동하지만, toThrowError 매처와 함께 사용하기 위해 오류 값을 예상합니다.

toHaveBeenCalled ​

  • 타입: () => Awaitable<void>

이 단언은 함수가 호출되었는지 여부를 테스트하는 데 유용합니다. expect에 스파이 함수를 전달해야 합니다.

ts
import { expect, test, vi } from 'vitest';

const market = {
  buy(subject: string, amount: number) {
    // ...
  },
};

test('모의 함수', () => {
  const buySpy = vi.spyOn(market, 'buy');

  expect(buySpy).not.toHaveBeenCalled();

  market.buy('apples', 10);

  expect(buySpy).toHaveBeenCalled();
});

toHaveBeenCalledTimes ​

  • 타입: (amount: number) => Awaitable<void>

이 단언은 함수가 특정 횟수만큼 호출되었는지 확인합니다. expect에 스파이 함수를 전달해야 합니다.

ts
import { expect, test, vi } from 'vitest';

const market = {
  buy(subject: string, amount: number) {
    // ...
  },
};

test('모의 함수가 두 번 호출되었는지 확인', () => {
  const buySpy = vi.spyOn(market, 'buy');

  market.buy('apples', 10);
  market.buy('apples', 20);

  expect(buySpy).toHaveBeenCalledTimes(2);
});

toHaveBeenCalledWith ​

  • 타입: (...args: any[]) => Awaitable<void>

이 단언은 함수가 특정 매개변수를 사용하여 최소 한 번 이상 호출되었는지 확인합니다. expect에 스파이 함수를 전달해야 합니다.

ts
import { expect, test, vi } from 'vitest';

const market = {
  buy(subject: string, amount: number) {
    // ...
  },
};

test('모의 함수', () => {
  const buySpy = vi.spyOn(market, 'buy');

  market.buy('apples', 10);
  market.buy('apples', 20);

  expect(buySpy).toHaveBeenCalledWith('apples', 10);
  expect(buySpy).toHaveBeenCalledWith('apples', 20);
});

toHaveBeenLastCalledWith ​

  • 타입: (...args: any[]) => Awaitable<void>

이 단언은 함수가 마지막으로 호출되었을 때 특정 매개변수를 사용하여 호출되었는지 확인합니다. expect에 스파이 함수를 전달해야 합니다.

ts
import { expect, test, vi } from 'vitest';

const market = {
  buy(subject: string, amount: number) {
    // ...
  },
};

test('모의 함수', () => {
  const buySpy = vi.spyOn(market, 'buy');

  market.buy('apples', 10);
  market.buy('apples', 20);

  expect(buySpy).not.toHaveBeenLastCalledWith('apples', 10);
  expect(buySpy).toHaveBeenLastCalledWith('apples', 20);
});

toHaveBeenNthCalledWith ​

  • 타입: (time: number, ...args: any[]) => Awaitable<void>

이 단언은 함수가 특정 순서로 호출되었을 때 특정 매개변수를 사용하여 호출되었는지 확인합니다. 호출 횟수는 1부터 시작합니다. 따라서 두 번째 호출을 확인하려면 .toHaveBeenNthCalledWith(2, ...)와 같이 작성합니다.

expect에 스파이 함수를 전달해야 합니다.

ts
import { expect, test, vi } from 'vitest';

const market = {
  buy(subject: string, amount: number) {
    // ...
  },
};

test('스파이 함수의 첫 번째 호출이 올바른 매개변수로 호출됨', () => {
  const buySpy = vi.spyOn(market, 'buy');

  market.buy('apples', 10);
  market.buy('apples', 20);

  expect(buySpy).toHaveBeenNthCalledWith(1, 'apples', 10);
});

toHaveReturned ​

  • 타입: () => Awaitable<void>

이 단언은 함수가 최소 한 번 이상 성공적으로 값을 반환했는지 확인합니다 (즉, 오류를 발생시키지 않았는지 확인합니다). expect에 스파이 함수를 전달해야 합니다.

ts
import { expect, test, vi } from 'vitest';

function getApplesPrice(amount: number) {
  const PRICE = 10;
  return amount * PRICE;
}

test('모의 함수가 값을 반환함', () => {
  const getPriceSpy = vi.fn(getApplesPrice);

  const price = getPriceSpy(10);

  expect(price).toBe(100);
  expect(getPriceSpy).toHaveReturned();
});

toHaveReturnedTimes ​

  • 타입: (amount: number) => Awaitable<void>

이 단언은 함수가 정확히 지정된 횟수만큼 성공적으로 값을 반환했는지 확인합니다 (즉, 오류를 발생시키지 않았는지 확인합니다). expect에 스파이 함수를 전달해야 합니다.

ts
import { expect, test, vi } from 'vitest';

test('모의 함수가 두 번 값을 반환했는지 확인', () => {
  const sell = vi.fn((product: string) => ({ product }));

  sell('apples');
  sell('bananas');

  expect(sell).toHaveReturnedTimes(2);
});

toHaveReturnedWith ​

  • 타입: (returnValue: any) => Awaitable<void>

이 어설션은 함수가 특정 인수로 호출되어 최소 한 번 이상 성공적으로 값을 반환했는지 확인합니다. expect에 스파이 함수를 전달해야 합니다.

ts
import { expect, test, vi } from 'vitest';

test('스파이 함수가 제품을 반환합니다', () => {
  const sell = vi.fn((product: string) => ({ product }));

  sell('사과');

  expect(sell).toHaveReturnedWith({ product: '사과' });
});

toHaveLastReturnedWith ​

  • 타입: (returnValue: any) => Awaitable<void>

이 어설션은 함수가 마지막 호출에서 특정 인수를 사용하여 값을 성공적으로 반환했는지 확인합니다. expect에 스파이 함수를 전달해야 합니다.

ts
import { expect, test, vi } from 'vitest';

test('스파이 함수가 마지막 호출에서 바나나를 반환합니다', () => {
  const sell = vi.fn((product: string) => ({ product }));

  sell('사과');
  sell('바나나');

  expect(sell).toHaveLastReturnedWith({ product: '바나나' });
});

toHaveNthReturnedWith ​

  • 타입: (time: number, returnValue: any) => Awaitable<void>

이 어설션은 함수가 특정 번째 호출에서 특정 인수를 사용하여 값을 성공적으로 반환했는지 확인합니다. expect에 스파이 함수를 전달해야 합니다.

ts
import { expect, test, vi } from 'vitest';

test('스파이 함수가 두 번째 호출에서 바나나를 반환합니다', () => {
  const sell = vi.fn((product: string) => ({ product }));

  sell('사과');
  sell('바나나');

  expect(sell).toHaveNthReturnedWith(2, { product: '바나나' });
});

toSatisfy ​

  • 타입: (predicate: (value: any) => boolean) => Awaitable<void>

이 어설션은 값이 주어진 조건 함수를 만족하는지 확인합니다.

ts
import { describe, expect, it } from 'vitest';
describe('toSatisfy()', () => {
  const isOdd = (value: number) => value % 2 !== 0;

  it('1로 통과', () => {
    expect(1).toSatisfy(isOdd);
  });

  it('부정일 때 통과', () => {
    expect(2).not.toSatisfy(isOdd);
  });
});

resolves ​

  • 타입: Promisify<Assertions>

resolves는 비동기 코드에 대한 어설션을 더 쉽게 작성할 수 있도록 도와줍니다. Promise가 성공적으로 이행되었을 때의 값을 추출하여 일반적인 어설션으로 검증하는 데 사용됩니다. Promise가 거부되면 어설션은 실패합니다.

동일한 Assertions 객체를 반환하지만, 모든 매처가 이제 Promise를 반환하므로 await해야 합니다. chai 어설션과도 호환됩니다.

예를 들어 API 호출을 수행하고 데이터를 반환하는 함수가 있는 경우, 다음 코드를 사용하여 반환 값을 어설션할 수 있습니다.

ts
import { expect, test } from 'vitest';

async function buyApples() {
  return fetch('/buy/apples').then(r => r.json());
}

test('buyApples는 새 재고 ID를 반환합니다', async () => {
  // toEqual은 이제 프로미스를 반환하므로 await해야 합니다.
  await expect(buyApples()).resolves.toEqual({ id: 1 }); // jest API
  await expect(buyApples()).resolves.to.equal({ id: 1 }); // chai API
});

WARNING

어설션을 await하지 않으면 매번 통과하는 오탐(false positive) 테스트가 발생할 수 있습니다. 어설션이 실제로 호출되었는지 확인하려면 expect.assertions(number)를 사용해야 합니다.

rejects ​

  • 타입: Promisify<Assertions>

rejects는 비동기 코드에 대한 어설션을 더 쉽게 작성할 수 있도록 도와줍니다. Promise가 거부되었을 때의 이유를 추출하여 일반적인 어설션으로 검증하는 데 사용됩니다. Promise가 성공적으로 이행되면 어설션은 실패합니다.

동일한 Assertions 객체를 반환하지만, 모든 매처가 이제 Promise를 반환하므로 await해야 합니다. chai 어설션과도 호환됩니다.

예를 들어 호출 시 실패하는 함수가 있는 경우, 다음 코드를 사용하여 거부 이유를 어설션할 수 있습니다.

ts
import { expect, test } from 'vitest';

async function buyApples(id) {
  if (!id) throw new Error('id가 없습니다');
}

test('id가 제공되지 않으면 buyApples가 오류를 발생시킵니다', async () => {
  // toThrow는 이제 프로미스를 반환하므로 await해야 합니다.
  await expect(buyApples()).rejects.toThrow('id가 없습니다');
});

WARNING

어설션을 await하지 않으면 매번 통과하는 오탐(false positive) 테스트가 발생할 수 있습니다. 어설션이 실제로 호출되었는지 확인하려면 expect.assertions(number)를 사용해야 합니다.

expect.assertions ​

  • 타입: (count: number) => void

테스트가 완료된 후, 테스트 중에 특정 횟수의 어설션이 호출되었는지 확인합니다. 비동기 코드의 어설션 실행 여부를 확인할 때 유용합니다.

예를 들어 두 개의 매처를 비동기적으로 호출하는 함수가 있는 경우, 실제로 호출되었는지 어설션할 수 있습니다.

ts
import { expect, test } from 'vitest';

async function doAsync(...cbs) {
  await Promise.all(cbs.map((cb, index) => cb({ index })));
}

test('모든 어설션이 호출됩니다', async () => {
  expect.assertions(2);
  function callback1(data) {
    expect(data).toBeTruthy();
  }
  function callback2(data) {
    expect(data).toBeTruthy();
  }

  await doAsync(callback1, callback2);
});

WARNING

비동기 동시 테스트와 함께 assertions를 사용하는 경우, 올바른 테스트가 감지되도록 로컬 테스트 컨텍스트의 expect를 사용해야 합니다.

expect.hasAssertions ​

  • 타입: () => void

테스트가 완료된 후, 테스트 중에 최소 하나의 어설션이 호출되었는지 확인합니다. 비동기 코드의 어설션 실행 여부를 확인할 때 유용합니다.

예를 들어 콜백을 호출하는 코드가 있는 경우, 콜백 내에서 어설션을 만들 수 있지만 어설션이 호출되었는지 확인하지 않으면 테스트가 항상 통과합니다.

ts
import { expect, test } from 'vitest';
import { db } from './db.js';

const cbs = [];

function onSelect(cb) {
  cbs.push(cb);
}

// db에서 선택한 후 모든 콜백을 호출합니다.
function select(id) {
  return db.select({ id }).then(data => {
    return Promise.all(cbs.map(cb => cb(data)));
  });
}

test('콜백이 호출되었습니다', async () => {
  expect.hasAssertions();
  onSelect(data => {
    // 선택 시 호출되어야 합니다.
    expect(data).toBeTruthy();
  });
  // 기다리지 않으면 테스트가 실패합니다.
  // expect.hasAssertions()가 없으면 테스트가 통과합니다.
  await select(3);
});

expect.unreachable ​

  • 타입: (message?: string) => never

이 메서드는 특정 코드 줄이 실행되지 않아야 함을 나타낼 때 사용됩니다.

예를 들어 build() 함수가 src 폴더가 없는 디렉터리를 인수로 받아 예외를 발생시키는지 테스트하고, 각 오류를 개별적으로 처리하려는 경우 다음과 같이 할 수 있습니다.

ts
import { expect, test } from 'vitest';

async function build(dir) {
  if (dir.includes('no-src')) throw new Error(`${dir}/src가 존재하지 않습니다`);
}

const errorDirs = [
  'no-src-folder',
  // ...
];

test.each(errorDirs)('build가 "%s"로 실패합니다', async dir => {
  try {
    await build(dir);
    expect.unreachable('빌드를 통과해서는 안 됩니다');
  } catch (err: any) {
    expect(err).toBeInstanceOf(Error);
    expect(err.stack).toContain('build');

    switch (dir) {
      case 'no-src-folder':
        expect(err.message).toBe(`${dir}/src가 존재하지 않습니다`);
        break;
      default:
        // 모든 오류 케이스를 처리하기 위해
        expect.unreachable('모든 오류 테스트를 처리해야 합니다');
        break;
    }
  }
});

expect.anything ​

  • 타입: () => any

이 비대칭 매처는 값 비교 시 항상 true를 반환합니다. 속성의 존재 여부만 확인할 때 유용합니다.

ts
import { expect, test } from 'vitest';

test('객체에 "apples" 키가 있습니다', () => {
  expect({ apples: 22 }).toEqual({ apples: expect.anything() });
});

expect.any ​

  • 타입: (constructor: unknown) => any

이 비대칭 매처는 값 비교 시 값이 지정된 생성자의 인스턴스인 경우에만 true를 반환합니다. 매번 값이 생성될 때, 해당 값이 올바른 타입인지 확인할 때 유용합니다.

ts
import { expect, test } from 'vitest';
import { generateId } from './generators.js';

test('"id"는 숫자입니다', () => {
  expect({ id: generateId() }).toEqual({ id: expect.any(Number) });
});

expect.closeTo 1.0.0+ ​

  • 타입: (expected: any, precision?: number) => any

expect.closeTo는 객체 속성 또는 배열 항목에서 부동 소수점 숫자를 비교할 때 유용합니다. 숫자를 비교해야 하는 경우 대신 .toBeCloseTo를 사용하십시오.

선택적 numDigits 인수는 소수점 아래에서 확인할 자릿수를 제한합니다. 기본값 2의 경우 테스트 기준은 Math.abs(expected - received) < 0.005 (즉, 10 ** -2 / 2)입니다.

예를 들어, 다음 테스트는 5자리 정밀도로 통과합니다.

js
test('compare float in object properties', () => {
  expect({
    title: '0.1 + 0.2',
    sum: 0.1 + 0.2,
  }).toEqual({
    title: '0.1 + 0.2',
    sum: expect.closeTo(0.3, 5),
  });
});

expect.arrayContaining ​

  • 타입: <T>(expected: T[]) => any

이 비대칭 매처는 값 비교 시 값이 배열이고 지정된 항목을 포함하는 경우 true를 반환합니다.

ts
import { expect, test } from 'vitest';

test('바구니에 후지(Fuji)가 포함되어 있습니다', () => {
  const basket = {
    varieties: ['Empire', 'Fuji', 'Gala'],
    count: 3,
  };
  expect(basket).toEqual({
    count: 3,
    varieties: expect.arrayContaining(['Fuji']),
  });
});

TIP

expect.not과 함께 사용하면 예상 값을 반대로 검증할 수 있습니다.

expect.objectContaining ​

  • 타입: (expected: any) => any

이 비대칭 매처는 값 비교 시 값이 지정된 속성을 포함하는 객체인 경우 true를 반환합니다.

ts
import { expect, test } from 'vitest';

test('바구니에 엠파이어(Empire) 사과가 있습니다', () => {
  const basket = {
    varieties: [
      {
        name: 'Empire',
        count: 1,
      },
    ],
  };
  expect(basket).toEqual({
    varieties: [expect.objectContaining({ name: 'Empire' })],
  });
});

TIP

expect.not과 함께 사용하면 예상 값을 반대로 검증할 수 있습니다.

expect.stringContaining ​

  • 타입: (expected: any) => any

이 비대칭 매처는 값 비교 시 값이 문자열이고 지정된 하위 문자열을 포함하는 경우 true를 반환합니다.

ts
import { expect, test } from 'vitest';

test('사과 품종 이름에 "Emp"가 있습니다', () => {
  const variety = {
    name: 'Empire',
    count: 1,
  };
  expect(variety).toEqual({
    name: expect.stringContaining('Emp'),
    count: 1,
  });
});

TIP

expect.not과 함께 사용하면 예상 값을 반대로 검증할 수 있습니다.

expect.stringMatching ​

  • 타입: (expected: any) => any

이 비대칭 매처는 값 비교 시 값이 문자열이고 지정된 하위 문자열을 포함하거나 문자열이 정규식과 일치하는 경우 true를 반환합니다.

ts
import { expect, test } from 'vitest';

test('사과 품종이 "re"로 끝납니다', () => {
  const variety = {
    name: 'Empire',
    count: 1,
  };
  expect(variety).toEqual({
    name: expect.stringMatching(/re$/),
    count: 1,
  });
});

TIP

expect.not과 함께 사용하면 예상 값을 반대로 검증할 수 있습니다.

expect.addSnapshotSerializer ​

  • 타입: (plugin: PrettyFormatPlugin) => void

이 메서드는 스냅샷을 생성할 때 호출되는 사용자 지정 직렬 변환기를 추가합니다. 이는 고급 사용자를 위한 기능입니다. 자세한 내용은 사용자 지정 직렬 변환기 가이드를 참조하십시오.

커스텀 직렬 변환기를 추가하려면 setupFiles 내에서 이 메서드를 호출해야 합니다. 이는 모든 스냅샷에 적용됩니다.

TIP

이전에 Jest와 함께 Vue CLI를 사용한 경우 jest-serializer-vue를 설치하는 것이 좋습니다. 그렇지 않으면 스냅샷이 문자열로 래핑되어 "가 이스케이프 처리될 수 있습니다.

expect.extend ​

  • 타입: (matchers: MatchersObject) => void

기본 매처를 직접 확장할 수 있습니다. 이 함수는 사용자 지정 매처를 정의하여 매처 객체를 확장하는 데 사용됩니다.

이러한 방식으로 매처를 정의하면 expect.stringContaining처럼 사용할 수 있는 비대칭 매처 또한 생성됩니다.

ts
import { expect, test } from 'vitest';

test('사용자 지정 매처', () => {
  expect.extend({
    toBeFoo: (received, expected) => {
      if (received !== 'foo') {
        return {
          message: () => `expected ${received} to be foo`,
          pass: false,
        };
      }
    },
  });

  expect('foo').toBeFoo();
  expect({ foo: 'foo' }).toEqual({ foo: expect.toBeFoo() });
});

TIP

매처가 모든 테스트에 나타나도록 하려면 setupFiles 내에서 이 메서드를 호출해야 합니다.

이 함수는 Jest의 expect.extend와 호환되므로, 사용자 지정 매처를 만드는 데 사용하는 모든 라이브러리가 Vitest와 함께 작동합니다.

TypeScript를 사용하는 경우, Vitest 0.31.0부터 다음 코드를 사용하여 앰비언트 선언 파일(예: vitest.d.ts)에서 기본 Assertion 인터페이스를 확장할 수 있습니다.

ts
interface CustomMatchers<R = unknown> {
  toBeFoo: () => R;
}

declare module 'vitest' {
  interface Assertion<T = any> extends CustomMatchers<T> {}
  interface AsymmetricMatchersContaining extends CustomMatchers {}
}

WARNING

앰비언트 선언 파일 포함을 잊지 마세요.

TIP

자세한 내용은 매처 확장 가이드를 참조하십시오.

expect.addEqualityTesters 1.2.0+ ​

  • 타입: (tester: Array<Tester>) => void

이 메서드를 사용하면 사용자 정의 테스터를 정의할 수 있습니다. 이는 두 객체가 동일한지 테스트하기 위해 매처에서 사용되는 메서드입니다. 이는 Jest의 expect.addEqualityTesters와 호환됩니다.

ts
import { expect, test } from 'vitest';

class AnagramComparator {
  public word: string;

  constructor(word: string) {
    this.word = word;
  }

  equals(other: AnagramComparator): boolean {
    const cleanStr1 = this.word.replace(/ /g, '').toLowerCase();
    const cleanStr2 = other.word.replace(/ /g, '').toLowerCase();

    const sortedStr1 = cleanStr1.split('').sort().join('');
    const sortedStr2 = cleanStr2.split('').sort().join('');

    return sortedStr1 === sortedStr2;
  }
}

function isAnagramComparator(a: unknown): a is AnagramComparator {
  return a instanceof AnagramComparator;
}

function areAnagramsEqual(a: unknown, b: unknown): boolean | undefined {
  const isAAnagramComparator = isAnagramComparator(a);
  const isBAnagramComparator = isAnagramComparator(b);

  if (isAAnagramComparator && isBAnagramComparator) return a.equals(b);
  else if (isAAnagramComparator === isBAnagramComparator) return undefined;
  else return false;
}

expect.addEqualityTesters([areAnagramsEqual]);

test('custom equality tester', () => {
  expect(new AnagramComparator('listen')).toEqual(
    new AnagramComparator('silent')
  );
});
Pager
이전Vi
다음expectTypeOf

MIT 라이선스 하에 배포되었습니다.

Copyright (c) 2024 Mithril Contributors

https://v1.vitest.dev/api/expect

MIT 라이선스 하에 배포되었습니다.

Copyright (c) 2024 Mithril Contributors