Jest 매처로 값 검증하기
Jest 매처로 값 검증하기 (Using Matchers)
테스트라고 해서 처음부터 복잡한 프레임워크 지식이 필요하진 않아요. Jest에서는 expect()로 값을 잡고, 그 위에 **매처(matcher)**라는 검증 도구만 얹으면 대부분의 단언(assertion)을 끝낼 수 있죠. 이 글에서는 가장 자주 쓰는 매처들을 상황별로 정리해 볼게요. 모든 매처의 전체 목록은 expect API 문서에서 확인할 수 있어요.
흔히 쓰는 매처
값을 검증하는 가장 간단한 방법은 완전 일치를 비교하는 거예요. 아래 코드에서 expect(2 + 2)는 expectation 객체를 돌려주는데, 우리는 이 객체에 매처를 호출하는 것 외에는 별로 할 일이 없어요. .toBe(4)가 바로 매처죠. Jest는 실행하면서 실패한 매처를 모두 기억해 두었다가 나중에 보기 좋은 에러 메시지로 출력해 줘요.
test('two plus two is four', () => {
expect(2 + 2).toBe(4);
});
toBe는 Object.is를 사용해 완전 일치를 검사해요. 객체의 값까지 비교하고 싶다면 toEqual을 사용하면 되는데, 이 매처는 객체나 배열의 모든 필드를 재귀적으로 확인해요.
test('object assignment', () => {
const data = {one: 1};
data['two'] = 2;
expect(data).toEqual({one: 1, two: 2});
});
:::tip
toEqual은 undefined 값을 가진 키, undefined 배열 요소, 배열의 빈 틈(sparse), 객체 타입 불일치는 무시해요. 이런 부분까지 정확히 잡아내고 싶다면 toStrictEqual을 쓰면 돼요.
:::
매처 앞에 not을 붙이면 반대 조건을 검사할 수 있어요.
test('adding positive numbers is not zero', () => {
for (let a = 1; a < 10; a++) {
for (let b = 1; b < 10; b++) {
expect(a + b).not.toBe(0);
}
}
});
진위값 (Truthiness)
테스트를 짜다 보면 undefined와 null, false를 구분해야 하는 경우가 있는 반면, 이 셋을 굳이 다르게 취급하고 싶지 않은 경우도 있어요. Jest는 내가 원하는 기준을 분명히 드러낼 수 있도록 도와주는 매처들을 갖추고 있죠.
toBeNull:null만 매치해요toBeUndefined:undefined만 매치해요toBeDefined:toBeUndefined의 반대예요toBeTruthy:if문이 참으로 평가하는 모든 값을 매치해요toBeFalsy:if문이 거짓으로 평가하는 모든 값을 매치해요
예를 들어 이런 식으로 써요.
test('null', () => {
const n = null;
expect(n).toBeNull();
expect(n).toBeDefined();
expect(n).not.toBeUndefined();
expect(n).not.toBeTruthy();
expect(n).toBeFalsy();
});
test('zero', () => {
const z = 0;
expect(z).not.toBeNull();
expect(z).toBeDefined();
expect(z).not.toBeUndefined();
expect(z).not.toBeTruthy();
expect(z).toBeFalsy();
});
이름에서 알 수 있듯, 코드가 하려는 일을 가장 정확하게 묘사하는 매처를 골라 쓰는 게 좋아요.
숫자
숫자 비교도 대부분 매처로 치환할 수 있어요.
test('two plus two', () => {
const value = 2 + 2;
expect(value).toBeGreaterThan(3);
expect(value).toBeGreaterThanOrEqual(3.5);
expect(value).toBeLessThan(5);
expect(value).toBeLessThanOrEqual(4.5);
// toBe and toEqual are equivalent for numbers
expect(value).toBe(4);
expect(value).toEqual(4);
});
부동소수점을 비교할 때는 toEqual 대신 toBeCloseTo를 쓰는 게 안전해요. 아주 작은 반올림 오차 하나 때문에 테스트가 깨지길 원하는 사람은 없으니까요.
test('adding floating point numbers', () => {
const value = 0.1 + 0.2;
//expect(value).toBe(0.3); This won't work because of rounding error
expect(value).toBeCloseTo(0.3); // This works.
});
문자열
정규식으로 문자열을 검사하고 싶다면 toMatch를 쓰면 돼요.
test('there is no I in team', () => {
expect('team').not.toMatch(/I/);
});
test('but there is a "stop" in Christoph', () => {
expect('Christoph').toMatch(/stop/);
});
배열과 이터러블
배열이나 이터러블이 특정 항목을 포함하는지 확인할 때는 toContain을 사용해요.
const shoppingList = [
'diapers',
'kleenex',
'trash bags',
'paper towels',
'milk',
];
test('the shopping list has milk on it', () => {
expect(shoppingList).toContain('milk');
expect(new Set(shoppingList)).toContain('milk');
});
예외
특정 함수가 호출될 때 에러를 던지는지 확인하고 싶다면 toThrow를 사용해요.
function compileAndroidCode() {
throw new Error('you are using the wrong JDK!');
}
test('compiling android goes as expected', () => {
expect(() => compileAndroidCode()).toThrow();
expect(() => compileAndroidCode()).toThrow(Error);
// You can also use a string that must be contained in the error message or a regexp
expect(() => compileAndroidCode()).toThrow('you are using the wrong JDK');
expect(() => compileAndroidCode()).toThrow(/JDK/);
// Or you can match an exact error message using a regexp like below
expect(() => compileAndroidCode()).toThrow(/^you are using the wrong JDK$/); // Test fails
expect(() => compileAndroidCode()).toThrow(/^you are using the wrong JDK!$/); // Test pass
});
:::tip
예외를 던지는 함수는 반드시 감싸는 함수 안에서 호출해야 해요. 그렇지 않으면 toThrow 단언이 제대로 동작하지 않아요.
:::
더 알아보기
이제 매처의 맛을 보았으니, 다음 단계로는 Jest가 비동기 코드를 테스트하는 방법을 살펴보는 걸 추천해요. 매처 하나하나의 전체 규칙이 궁금하다면 expect API 레퍼런스를 참고하세요.