여러분들은 Jest로 테스트 코드를 작성할 때 다양한 Matcher를 사용하고 계시나요?
오늘은 Jest에서 테스트 코드를 작성할 때 자주 사용하는 Matcher에 대해서 알아보겠습니다.
1. toBe( value )
기본형을 비교할 때 자주 사용합니다. 값이 같은지 비교합니다.
대상이 원시형(primitive type)이라면 값을 비교하고,
참조형(reference type)이라면 같은 대상을 참조하는지 비교합니다. (얕은 비교)
describe("toBe 테스트", () => {
test("원시형 비교", () => {
const result = "123";
expect(result).toBe("123"); // test passed!
});
test("참조형 비교", () => {
const result = [1, 2, 3];
expect(result).toBe([1, 2, 3]); // test failed!
});
});
때문에 위 테스트 코드에서 참조형인 배열 [1,2,3]의 toBe( ) 테스트는 실패하게 됩니다.
2. toEqual( value )
참조형을 비교할 때 자주 사용됩니다. 참조형의 모든 필드(프로퍼티, 요소)를 재귀적으로 돌며 비교해 줍니다. (깊은 비교)
원시형도 비교 가능합니다.
describe("toEqual 테스트", () => {
test("원시형 비교", () => {
const result = "123";
expect(result).toEqual("123"); // test passed!
});
test("참조형 비교", () => {
const result = [1, 2, 3];
expect(result).toEqual([1, 2, 3]); // test passed!
});
});
toBe( ) 테스트와 다르게 참조형인 배열의 toEqual() 테스트가 통과했습니다.
💢 주의할 점
객체의 프로퍼티나, 배열의 요소에 undefined가 추가되어 있어도 테스트는 통과됩니다.
describe("toEqual undefined 테스트", () => {
test("참조형 비교 - 객체", () => {
const result = { a: 1, b: 2 };
expect(result).toEqual({ a: 1, b: 2, c: undefined }); // test passed!!!!????
});
test("참조형 비교 - 배열", () => {
const result = [1, 2, 3];
expect(result).toEqual([1, 2, 3, undefined]); // test passed!!!!!???
});
});
위 테스트 결과처럼 toEqual( ) 사용시 이 점에 유의하여 테스트 코드를 작성해야 합니다.
3. toStrictEqual( value )
위와 같은 toEqual( )의 문제를 toStrictEqual( )로 해결할 수 있습니다.
toStrictEqual( )은 undefined까지 비교합니다.
describe("toStrictEqual undefined 테스트", () => {
test("참조형 비교 - 객체", () => {
const result = { a: 1, b: 2 };
expect(result).toStrictEqual({ a: 1, b: 2, c: undefined }); // test failed ^^
});
test("참조형 비교 - 배열", () => {
const result = [1, 2, 3];
expect(result).toStrictEqual([1, 2, 3, undefined]); // test failed ^^
});
});
위 테스트는 실패합니다.
jest 공식 문서에서도 이러한 특징때문에 toStrictEqual( ) 이 선호된다고 알려주네요!
💢 꼼꼼한 toStrictEqual( )
toStrcitEqual( )은 객체의 인스턴스 타입까지 비교합니다.
describe.only("toEqual vs toStrictEqual 인스턴스 테스트", () => {
class Test {
constructor(test) {
this.test = test;
}
}
test("toEqual 인스턴스 테스트", () => {
const instance = new Test(1);
const normal = { test: 1 };
expect(normal).toEqual(instance); // test passed !!
});
test("toStrictEqual 인스턴스 테스트", () => {
const instance = new Test(1);
const normal = { test: 1 };
expect(normal).toStrictEqual(instance); // test failed !!
});
});
같은 조건에 toEqual( ) 은 통과한 반면, toStrictEqual( )은 실패했습니다.
이 외에도 toStrictEqual( )은 [ ,1] 과 [undefined, 1] 을 다르다고 비교해 주는 등 보다 엄격하게 비교합니다.
toStrictEqual( )의 특징을 잘 활용하여 테스트 코드를 작성해 봅시다.
4. toBeTruthy( ), toBeFalsy( )
JS는 boolean 값을 true, false 만으로 한정하지 않습니다.
0, 빈 문자열 등을 false로 취급하는 것과 같이 말이죠.
이런값들을 비교할 때 toBeTrythy( ), toBeFalsy( )를 사용합니다.
describe("toBeTruthy / toBeFalsy 테스트", () => {
test("toBeTruthy 테스트", () => {
const result = "0";
expect(result).toBeTruthy(); // test passed !!
});
test("toBeFalsy 테스트", () => {
const result = 0;
expect(result).toBeFalsy(); // test passed !!
});
});
이 밖에도 Truthiness를 비교할 수 있는 matcher는 다양하니 알아두면 좋겠습니다.
- toBeNull: 대상이 null 인지 검증합니다.
- toBeUndefined: 대상이 undefined 인지 검증합니다.
- toBeDefined: 대상이 정의되었는지 검증합니다.
5. toContain( element )
배열이 특정 요소를 가지고 있는지 검증합니다.
배열, 문자열, Set, 노드 리스트, HTML 콜렉션과 같은 iterable에 사용할 수 있습니다.
describe("toContain 테스트", () => {
test("배열 테스트", () => {
const result = [1, 2, 3];
expect(result).toContain(1); // test passed !!
});
test("문자열 테스트", () => {
const result = "문자열 테스트";
expect(result).toContain("문자열"); // test passed !!
});
test("Set 테스트", () => {
const result = new Set([1, 2, 3]);
expect(result).toContain(1); // test passed !!
});
});
6. toHaveLength( number )
대상이 length 프로퍼티를 가지고 있는지, 또한 length의 길이가 일치하는지 검증합니다.
배열이나 문자열의 길이를 체크할 때 유용합니다.
describe("toHaveLength 테스트", () => {
test("배열 테스트", () => {
const result = [1, 2, 3];
expect(result).toHaveLength(3); // test passed !!
});
test("문자열 테스트", () => {
const result = "문자열 테스트";
expect(result).toHaveLength(7); // test passed !!
});
});
7. toThrow( error? )
대상 함수를 호출했을 때 에러가 발생하는지 여부를 검증합니다.
describe("toThrow 테스트", () => {
const testFunc = () => {
throw new Error("에러 테스트 함수입니다.");
};
const errorObj = new Error("에러 테스트 함수입니다.");
test("인자 X", () => {
expect(testFunc).toThrow(); // test passed !!
});
test("문자열 인자", () => {
expect(testFunc).toThrow("에러 테스트"); // test passed !!
});
test("Error 객체 인자", () => {
expect(testFunc).toThrow(errorObj); // test passed !!
});
test("클래스 인자", () => {
expect(testFunc).toThrow(Error); // test passed !!
});
});
인자에 따른 기능차이
- 인자가 없을 때: 에러 발생을 검증합니다.
- 문자열 인자: 에러 발생 + 에러 메시지가 인자로 전달한 문자열을 포함하는지 검증합니다.
- Error 객체 인자: 에러 발생 + 에러 메시지가 인자로 전달한 Error 객체의 메세지와 일치하는지 검증합니다.
- class 인자: 에러 발생 + 에러 객체가 인자로 전달한 class의 instance 인지 검증합니다.
8. toBeInstanceOf( Class )
대상 객체가 인자 클래스의 instance 인지 검증합니다.
describe("toBeInstanceOf 테스트", () => {
class Test {}
const output = new Test();
const fake = {};
test("인스턴스 O", () => {
expect(output).toBeInstanceOf(Test); // test passed !!
});
test("인스턴스 X", () => {
expect(fake).toBeInstanceOf(Test); // test failed !!
});
});
여기까지 다양한 matcher를 알아보았습니다.
소개한 matcher 외의 더 많은 matcher에 대한 정보들은 공식 문서에서 찾으실 수 있습니다.
다음 포스트에서는 mock의 개념과 mock 메서드, mock 함수에 사용하는 Matcher에 대해 알아보겠습니다!
'Testing' 카테고리의 다른 글
Testing - 테스트 코드의 목적과 규칙, Jest 기본 문법 (0) | 2022.11.03 |
---|