Skip to content

Jest의 expect 함수 ​

expect 함수는 값을 테스트하고 싶을 때마다 사용됩니다. 대부분의 경우, expect는 단독으로 호출되지 않으며, 대신 "matcher(matcher)" 함수와 함께 사용하여 값에 대해 어떤 것을 주장(assert)합니다.

기본 사용 예 ​

예를 들어, bestLaCroixFlavor() 메서드가 'grapefruit' 문자열을 반환해야 한다고 가정해 보겠습니다. 다음과 같이 테스트할 수 있습니다:

javascript
test("최고의 맛은 grapefruit이다", () => {
  expect(bestLaCroixFlavor()).toBe("grapefruit");
});

이 경우, toBe는 matcher 함수입니다. 다양한 matcher 함수들이 있어 다양한 것들을 테스트할 수 있도록 도와줍니다.

expect의 인자는 코드가 생성한 값을, matcher의 인자는 올바른 값을 가져야 합니다. 이를 혼동하면 테스트는 여전히 작동하지만, 실패한 테스트의 에러 메시지가 이상하게 보일 수 있습니다.

Modifiers ​

.not ​

어떤 것을 테스트하는 방법을 알고 있다면, .not을 사용하면 그 반대를 테스트할 수 있습니다. 예를 들어, 다음 코드는 최고의 La Croix 맛이 coconut이 아님을 테스트합니다:

javascript
test("최고의 맛은 coconut이 아니다", () => {
  expect(bestLaCroixFlavor()).not.toBe("coconut");
});

.resolves와 .rejects ​

.resolves는 이행된 Promise의 값을 풀어서 다른 matcher를 연쇄적으로 사용할 수 있게 해줍니다. Promise가 거부되면 테스트는 실패합니다.

예를 들어, 다음 코드는 Promise가 이행되고 그 결과 값이 'lemon'이 되는 것을 테스트합니다:

javascript
test("lemon으로 이행된다", async () => {
  await expect(Promise.resolve("lemon")).resolves.toBe("lemon");
  await expect(Promise.resolve("lemon")).resolves.not.toBe("octopus");
});

.rejects는 거부된 Promise의 풀어서 다른 matcher를 연쇄적으로 사용할 수 있게 해줍니다. Promise가 이행되면 테스트는 실패합니다.

예를 들어, 다음 코드는 Promise가 'octopus'라는 이유로 거부되는 것을 테스트합니다:

javascript
test("octopus로 거부된다", async () => {
  await expect(Promise.reject(new Error("octopus"))).rejects.toThrow("octopus");
});

Matchers ​

Jest에서 Matchers는 테스트할 값에 대해 다양한 주장(assertions)을 할 수 있게 해주는 함수들입니다. 여기서는 주요 Matchers와 그 사용법을 살펴보겠습니다.

값 비교하기 ​

.toBe(value) *** ​

  • 원시 값이나 객체 인스턴스의 참조 동일성을 비교할 때 사용합니다.
  • Object.is를 사용해 값 비교를 수행하기 때문에, ===보다 테스트에 적합합니다.
javascript
test("has 12 ounces", () => {
  expect(can.ounces).toBe(12);
});

주의: 부동 소수점 수 비교 ​

  • .toBe는 부동 소수점 수에 대해서는 사용하지 않는 것이 좋습니다. 대신, .toBeCloseTo를 사용하세요.

Mock 함수 호출 검사 ​

.toHaveBeenCalled() *** ​

  • Mock 함수가 최소 한 번 이상 호출되었는지 검사합니다.
javascript
test("drinks something lemon-flavoured", () => {
  const drink = jest.fn();
  drinkAll(drink, "lemon");
  expect(drink).toHaveBeenCalled();
});

.toHaveBeenCalledTimes(number) *** ​

  • Mock 함수가 정확히 지정된 횟수만큼 호출되었는지 검사합니다.
javascript
test("drinkEach drinks each drink", () => {
  const drink = jest.fn();
  drinkEach(drink, ["lemon", "octopus"]);
  expect(drink).toHaveBeenCalledTimes(2);
});

.toHaveBeenCalledWith(arg1, arg2, ...) *** ​

  • Mock 함수가 특정 인자로 호출되었는지 검사합니다.
javascript
test("registration applies correctly to orange La Croix", () => {
  const beverage = new LaCroix("orange");
  register(beverage);
  const f = jest.fn();
  applyToAll(f);
  expect(f).toHaveBeenCalledWith(beverage);
});

.toHaveBeenLastCalledWith(arg1, arg2, ...) ​

  • Mock 함수가 마지막으로 호출될 때 특정 인자로 호출되었는지 검사합니다.
javascript
test("applying to all flavors does mango last", () => {
  const drink = jest.fn();
  applyToAllFlavors(drink);
  expect(drink).toHaveBeenLastCalledWith("mango");
});

.toHaveBeenNthCalledWith(nthCall, arg1, arg2, ...) ​

  • Mock 함수가 n번째로 호출될 때 특정 인자로 호출되었는지 검사합니다.
javascript
test("drinkEach drinks each drink", () => {
  const drink = jest.fn();
  drinkEach(drink, ["lemon", "octopus"]);
  expect(drink).toHaveBeenNthCalledWith(1, "lemon");
  expect(drink).toHaveBeenNthCalledWith(2, "octopus");
});

반환 값 검사 ​

.toHaveReturned() ​

  • Mock 함수가 성공적으로 반환되었는지(즉, 에러를 던지지 않고) 최소 한 번 검사합니다.
javascript
test("drinks returns", () => {
  const drink = jest.fn(() => true);
  drink();
  expect(drink).toHaveReturned();
});

.toHaveReturnedTimes(number) ​

  • Mock 함수가 지정된 횟수만큼 성공적으로 반환되었는지 검사합니다.
javascript
test("drink returns twice", () => {
  const drink = jest.fn(() => true);
  drink();
  drink();
  expect(drink).toHaveReturnedTimes(2);
});

.toHaveReturnedWith(value) ​

  • Mock 함수가 특정 값을 반환했는지 검사합니다.
javascript
test("drink returns La Croix", () => {
  const beverage = { name: "La Croix" };
  const drink = jest.fn((beverage) => beverage.name);
  drink(beverage);
  expect(drink).toHaveReturnedWith("La Croix");
});

반환 값 검사 ​

.toHaveLastReturnedWith(value) ​

  • Mock 함수의 마지막 호출이 특정 값을 반환했는지 테스트합니다.
  • 마지막 호출이 에러를 발생시킨 경우, 어떤 반환 값이 제공되더라도 테스트는 실패합니다.
javascript
test("drink returns La Croix (Orange) last", () => {
  const beverage1 = { name: "La Croix (Lemon)" };
  const beverage2 = { name: "La Croix (Orange)" };
  const drink = jest.fn((beverage) => beverage.name);

  drink(beverage1);
  drink(beverage2);

  expect(drink).toHaveLastReturnedWith("La Croix (Orange)");
});

.toHaveNthReturnedWith(nthCall, value) ​

  • Mock 함수가 n번째 호출에서 특정 값을 반환했는지 테스트합니다.
  • n번째 호출이 에러를 발생시킨 경우, 제공된 반환 값에 상관없이 테스트는 실패합니다.
javascript
test("drink returns expected nth calls", () => {
  const beverage1 = { name: "La Croix (Lemon)" };
  const beverage2 = { name: "La Croix (Orange)" };
  const drink = jest.fn((beverage) => beverage.name);

  drink(beverage1);
  drink(beverage2);

  expect(drink).toHaveNthReturnedWith(1, "La Croix (Lemon)");
  expect(drink).toHaveNthReturnedWith(2, "La Croix (Orange)");
});

객체와 배열 검사 ​

.toHaveLength(number) ​

  • 객체가 .length 속성을 가지며, 이가 특정 수치 값과 동일한지 검사합니다.
  • 배열이나 문자열의 길이를 검사하는데 유용합니다.
javascript
expect([1, 2, 3]).toHaveLength(3);
expect("abc").toHaveLength(3);
expect("").not.toHaveLength(5);

.toHaveProperty(keyPath, value?) ​

  • 객체가 제공된 참조 keyPath에 해당하는 속성을 가지고 있는지, 선택적으로 해당 속성의 값이 기대하는 값과 동일한지 검사합니다.
  • 객체 내부의 깊숙히 중첩된 속성을 검사할 때 dot 표기법 또는 배열을 사용할 수 있습니다.
javascript
test("this house has my desired features", () => {
  // 단순 참조
  expect(houseForSale).toHaveProperty("bath");
  expect(houseForSale).toHaveProperty("bedrooms", 4);

  // 깊은 참조
  expect(houseForSale).toHaveProperty("kitchen.area", 20);
  expect(houseForSale).toHaveProperty(["kitchen", "nice.oven"]);
});

부동 소수점 수 검사 ​

.toBeCloseTo(number, numDigits?) ​

  • 부동 소수점 수의 근사 값을 검사할 때 사용합니다.
  • 선택적인 numDigits 인자로 소수점 이하 몇 번째 자리까지 비교할지 정할 수 있습니다.
javascript
test("adding works sanely with decimals", () => {
  expect(0.2 + 0.1).toBeCloseTo(0.3, 5); // 성공
});

정의 및 불리언 값 검사 ​

.toBeDefined() ​

  • 변수가 undefined가 아닌 값을 가지고 있는지 검사합니다.
javascript
test("there is a new flavor idea", () => {
  expect(fetchNewFlavorIdea()).toBeDefined();
});

.toBeFalsy() *** ​

  • 값이 불리언 컨텍스트에서 false로 평가되는지 검사합니다.
javascript
test("drinking La Croix does not lead to errors", () => {
  drinkSomeLaCroix();
  expect(getErrors()).toBeFalsy();
});

숫자 비교 Matchers ​

.toBeGreaterThan(number | bigint) ​

  • 받은 값이 기대하는 값보다 큰지 비교합니다.
javascript
test("ounces per can is more than 10", () => {
  expect(ouncesPerCan()).toBeGreaterThan(10);
});

.toBeGreaterThanOrEqual(number | bigint) ​

  • 받은 값이 기대하는 값보다 크거나 같은지 비교합니다.
javascript
test("ounces per can is at least 12", () => {
  expect(ouncesPerCan()).toBeGreaterThanOrEqual(12);
});

.toBeLessThan(number | bigint) ​

  • 받은 값이 기대하는 값보다 작은지 비교합니다.
javascript
test("ounces per can is less than 20", () => {
  expect(ouncesPerCan()).toBeLessThan(20);
});

.toBeLessThanOrEqual(number | bigint) ​

  • 받은 값이 기대하는 값보다 작거나 같은지 비교합니다.
javascript
test("ounces per can is at most 12", () => {
  expect(ouncesPerCan()).toBeLessThanOrEqual(12);
});

타입 및 상태 검사 Matchers ​

.toBeInstanceOf(Class) ​

  • 객체가 특정 클래스의 인스턴스인지 확인합니다.
javascript
class A {}
expect(new A()).toBeInstanceOf(A);

.toBeNull() *** ​

  • 값이 null인지 확인합니다.
javascript
function bloop() {
  return null;
}
test("bloop returns null", () => {
  expect(bloop()).toBeNull();
});

.toBeTruthy() *** ​

  • 값이 boolean 컨텍스트에서 true로 평가되는지 확인합니다.
javascript
test("drinking La Croix leads to having thirst info", () => {
  drinkSomeLaCroix();
  expect(thirstInfo()).toBeTruthy();
});

.toBeUndefined() *** ​

  • 값이 undefined인지 확인합니다.
javascript
test("the best drink for octopus flavor is undefined", () => {
  expect(bestDrinkForFlavor("octopus")).toBeUndefined();
});

.toBeNaN() ​

  • 값이 NaN인지 확인합니다.
javascript
test("passes when value is NaN", () => {
  expect(NaN).toBeNaN();
});

배열 및 객체 내 포함 여부 검사 Matchers ​

.toContain(item) *** ​

  • 배열이나 문자열이 특정 항목을 포함하고 있는지 확인합니다.
javascript
test("the flavor list contains lime", () => {
  expect(getAllFlavors()).toContain("lime");
});

.toContainEqual(item) ​

  • 배열이 주어진 객체와 동일한 구조와 값을 가진 항목을 포함하고 있는지 확인합니다.
javascript
describe("my beverage", () => {
  test("is delicious and not sour", () => {
    const myBeverage = { delicious: true, sour: false };
    expect(myBeverages()).toContainEqual(myBeverage);
  });
});

.toEqual(value) *** ​

  • 객체 또는 배열이 주어진 객체 또는 배열과 깊은 비교(deep equality)를 통해 동등한지 확인합니다.
javascript
describe("the La Croix cans on my desk", () => {
  const can1 = { flavor: "grapefruit", ounces: 12 };
  const can2 = { flavor: "grapefruit", ounces: 12 };

  test("have all the same properties", () => {
    expect(can1).toEqual(can2);
  });
});

문자열 매칭 검사 ​

.toMatch(regexp | string) *** ​

  • 문자열이 정규 표현식이나 문자열과 일치하는지 확인합니다.
javascript
describe("an essay on the best flavor", () => {
  test("mentions grapefruit", () => {
    expect(essayOnTheBestFlavor()).toMatch(/grapefruit/);
  });
});

describe("grapefruits are healthy", () => {
  test("grapefruits are a fruit", () => {
    expect("grapefruits").toMatch("fruit");
  });
});

객체 매칭 검사 ​

.toMatchObject(object) ​

  • JavaScript 객체가 주어진 객체의 속성과 부분적으로 일치하는지 확인합니다.
javascript
const houseForSale = {
  bath: true,
  bedrooms: 4,
  kitchen: {
    amenities: ["oven", "stove", "washer"],
    area: 20,
    wallColor: "white",
  },
};

const desiredHouse = {
  bath: true,
  kitchen: {
    amenities: ["oven", "stove", "washer"],
    wallColor: expect.stringMatching(/white|yellow/),
  },
};

test("the house has my desired features", () => {
  expect(houseForSale).toMatchObject(desiredHouse);
});

스냅샷 매칭 검사 ​

.toMatchSnapshot(propertyMatchers?, hint?) ​

  • 값이 최신 스냅샷과 일치하는지 확인합니다.
javascript
// 스냅샷 테스트 예제 코드는 생략되었습니다.

.toMatchInlineSnapshot(propertyMatchers?, inlineSnapshot) ​

  • 값이 인라인 스냅샷과 일치하는지 확인합니다. 스냅샷은 테스트 파일 내에 직접 포함됩니다.
javascript
// 인라인 스냅샷 테스트 예제 코드는 생략되었습니다.

엄격한 객체 비교 ​

.toStrictEqual(value) ​

  • 객체가 주어진 값과 정확히 같은지 확인합니다. .toEqual과는 달리, 더 엄격한 비교를 수행합니다.
javascript
class LaCroix {
  constructor(flavor) {
    this.flavor = flavor;
  }
}

describe("the La Croix cans on my desk", () => {
  test("are not semantically the same", () => {
    expect(new LaCroix("lemon")).toEqual({ flavor: "lemon" });
    expect(new LaCroix("lemon")).not.toStrictEqual({ flavor: "lemon" });
  });
});

예외 처리 검사 ​

.toThrow(error?) *** ​

  • 함수 호출 시 예외가 발생하는지 확인합니다.
javascript
test("throws on octopus", () => {
  expect(() => {
    drinkFlavor("octopus");
  }).toThrow();
});

.toThrowErrorMatchingSnapshot(hint?) ​

  • 함수가 호출될 때 발생하는 예외가 최신 스냅샷과 일치하는지 확인합니다.
javascript
test("throws on octopus", () => {
  function drinkOctopus() {
    drinkFlavor("octopus");
  }

  expect(drinkOctopus).toThrowErrorMatchingSnapshot();
});

.toThrowErrorMatchingInlineSnapshot(inlineSnapshot) ​

  • 함수가 호출될 때 발생하는 예외가 인라인 스냅샷과 일치하는지 확인합니다.

비대칭 Matchers ​

Jest의 비대칭 Matchers를 사용하면 테스트를 더 다양하고 유연하게 작성할 수 있습니다. 이들 Matchers는 특정 값이나 객체의 구조에 국한되지 않고, 더 넓은 범위의 조건을 테스트할 수 있게 해줍니다.

expect.anything() ​

  • null이나 undefined를 제외한 모든 것과 일치합니다.
javascript
test("map calls its argument with a non-null argument", () => {
  const mock = jest.fn();
  [1].map((x) => mock(x));
  expect(mock).toHaveBeenCalledWith(expect.anything());
});

expect.any(constructor) ​

  • 주어진 생성자로 생성된 모든 인스턴스나, 지정된 타입의 원시 값과 일치합니다.
javascript
class Cat {}
test("randocall calls its callback with a class instance", () => {
  const mock = jest.fn();
  getCat(mock);
  expect(mock).toHaveBeenCalledWith(expect.any(Cat));
});

test("randocall calls its callback with a number", () => {
  const mock = jest.fn();
  randocall(mock);
  expect(mock).toHaveBeenCalledWith(expect.any(Number));
});

expect.arrayContaining(array) ​

  • 받은 배열이 기대하는 배열의 모든 요소를 포함하는지 확인합니다. 즉, 기대하는 배열이 받은 배열의 부분집합인 경우 일치합니다.
javascript
describe("arrayContaining", () => {
  const expected = ["Alice", "Bob"];
  it("matches even if received contains additional elements", () => {
    expect(["Alice", "Bob", "Eve"]).toEqual(expect.arrayContaining(expected));
  });
});

expect.not.arrayContaining(array) ​

  • expect.arrayContaining의 반대로, 받은 배열이 기대하는 배열의 모든 요소를 포함하지 않는 경우 일치합니다.
javascript
describe("not.arrayContaining", () => {
  const expected = ["Samantha"];
  it("matches if the actual array does not contain the expected elements", () => {
    expect(["Alice", "Bob", "Eve"]).toEqual(
      expect.not.arrayContaining(expected)
    );
  });
});

expect.closeTo(number, numDigits?) ​

  • 객체의 속성이나 배열 요소로 있는 부동 소수점 수를 비교할 때 유용합니다.
javascript
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.objectContaining(object) ​

  • 받은 객체가 기대하는 객체의 속성을 재귀적으로 포함하는지 확인합니다.
javascript
test("onPress gets called with the right thing", () => {
  const onPress = jest.fn();
  simulatePresses(onPress);
  expect(onPress).toHaveBeenCalledWith(
    expect.objectContaining({
      x: expect.any(Number),
      y: expect.any(Number),
    })
  );
});

expect.not.objectContaining(object) ​

  • 받은 객체가 기대하는 객체의 속성을 재귀적으로 포함하지 않는 경우 일치합니다.
javascript
describe("not.objectContaining", () => {
  const expected = { foo: "bar" };
  it("matches if the actual object does not contain expected key: value pairs", () => {
    expect({ bar: "baz" }).toEqual(expect.not.objectContaining(expected));
  });
});

expect.stringContaining(string) 및 expect.not.stringContaining(string) ​

  • 받은 문자열이 기대하는 문자열을 포함하는지 혹은 포함하지 않는지 확인합니다.
javascript
describe("not.stringContaining", () => {
  const expected = "Hello world!";
  it("matches if the received value does not contain the expected substring", () => {
    expect("How are you?").toEqual(expect.not.stringContaining(expected));
  });
});

expect.stringMatching(string | regexp) 및 expect.not.stringMatching(string | regexp) ​

  • 받은 문자열이 기대하는 문자열이나 정규 표현식과 일치하는지 혹은 일치하지 않는지 확인합니다.
javascript
describe("stringMatching in arrayContaining", () => {
  const expected = [
    expect.stringMatching(/^Alic/),
    expect.stringMatching(/^[BR]ob/),
  ];
  it("matches even if received contains additional elements", () => {
    expect(["Alicia", "Roberto", "Evelina"]).toEqual(
      expect.arrayContaining(expected)
    );
  });
});