...
JEST Matcher 정리
Jest는 다른 방법으로 값을 테스트 하도록 matcher 라는 것을 사용한다.
matcher란 '이거 맞아?' 라고 물어보는 메서드리고 보면 된다. 기대한 값이 실제 반환된 값과 일치하는 지를 확인하는 작업을 일컫는다.
이번 포스팅에는 JEST에서 자주 쓰이는 matcher 함수 핵심만 꼽아 정리하는 시간을 가져 볼 것이다.
모든 matcher를 확인해보고 싶다면 expect에 대한 api 상세서 참고하자.
[ 테스트할 함수 ]
// user.js
// 테스트할 함수
function getUser(id) {
return {
id,
email: `user${id}@test.com`,
};
}
module.exports = getUser;
toEqual()
객체가 일치한지 검증한다. 왠만한 일치를 비교하려할때 이 메소드를 쓰면 된다.
const { getUser } = require('user'); // 테스트할 함수를 가져온다.
test("return a user object", () => {
// getUser(1)의 리턴 결과값이 { 객체 } 값이 같은 경우 true
expect(getUser(1)).toEqual({
id: 1,
email: `user1@test.com`,
});
});
toBe()
단순히 값 비교
expect(1 + 4).toBe(5);
toBeDefined()
변수가 정의되었는지 여부를 테스트
toBeTruthy() / toBeFalsy()
느슨한 타입 기반 언어인 자바스크립트는, 자바같은 강한 타입 기반 언어처럼 true와 false가 boolean 타입에 한정되지 않는다.
따라서 숫자 1이 true로 간주되고, 숫자 0이 false로 간주되는 것과 같이,
모든 타입의 값들을 true 아니면 false 간주하는 규칙이 있는데,
toBeTruthy() 는 검증 대상이 이 규칙에 따라 true로 간주되면 테스트 통과이고,
toBeFalsy() 는 반대로 false로 간주되는 경우 테스트가 통과된다.
test("number 0 is falsy but string 0 is truthy", () => {
expect(0).toBeFalsy(); // 숫자 0은 false를 의미하기도 하다. true
expect("0").toBeTruthy(); // 문자열은 true를 의미하기도 하다. true
});
toBeCalled() / toHaveBeenCalled()
함수가 호출되었는지 여부.
둘이 같은 역할을 하는 함수다.
function drinkAll(callback, flavour) {
if (flavour !== 'octopus') {
callback(flavour);
}
}
describe('drinkAll', () => {
test('drinks something lemon-flavoured', () => {
const drink = jest.fn();
drinkAll(drink, 'lemon');
expect(drink).toHaveBeenCalled(); // 함수 호출 O
});
test('does not drink something octopus-flavoured', () => {
const drink = jest.fn();
drinkAll(drink, 'octopus');
expect(drink).not.toHaveBeenCalled(); // 함수 호출 X
});
});
toHaveLength() / toContain()
배열의 경우에는 배열이 길이를 체크하거나 특정 원소가 존재 여부를 테스트하는 경우가 많다.
toHaveLength() 배열의 길이를 체크할 때 쓰이고,
toContain() 특정 원소가 배열에 들어있는지를 테스트할 때 쓰인다.
test("array", () => {
const colors = ["Red", "Yellow", "Blue"];
expect(colors).toHaveLength(3); // 배열길이 3
expect(colors).toContain("Yellow"); // Yellow 문자열 원소를 가지고 있는지
expect(colors).not.toContain("Green"); // Green 문자열 원소를 안가지고 있는지
});
toMatch()
문자열의 경우에는 단순히 toBe() 를 사용해서 문자열이 정확히 일치하는지를 체크하지만,
종종 정규식 기반의 테스트가 필요할 떄가 있는데 toMatch() 함수를 사용하면 된다.
test("string", () => {
expect(getUser(1).email).toBe("user1@test.com"); // 단순 문자열 비교
expect(getUser(2).email).toMatch(/.*test.com$/); // 정규식 비교
});
toThrow()
예외 발생 여부를 테스트해야할 때는 toThrow() 함수를 사용한다.
toThrow() 함수는 인자도 받는데, 문자열을 넘기면 예외 메세지를 비교하고 정규식을 넘기면 정규식 체크를 해준다.
위에서 작성한 getUser() 함수가 음수 아이디가 들어왔을 경우, 예외를 던지도록 수정해 보겠다.
// user.js
function getUser(id) {
if (id <= 0)
throw new Error("Invalid ID"); // id가 음수일경우 throw
return {
id,
email: `user${id}@test.com`,
};
}
module.exports = getUser;
주의할점은, toThrow() 함수를 사용할 때 반드시 expect() 함수에 넘기는 검증 대상을 함수로 한 번 감싸줘야 한다.
그렇지 않으면 예외 발생 여부를 체크하는 것이 아니라, 테스트 실행 도중 정말 그 예외가 발생하기 때문에 그 테스트는 항상 실패하게 되기 때문이다.
const { getUser } = require('user'); // 테스트할 함수를 가져온다.
test("throw when id is non negative", () => {
expect(() => getUser(-1)).toThrow(); // 예외를 검증할때는, 함수를 한번 더 감싸준다.
expect(() => getUser(-1)).toThrow("Invalid ID");
});
toHaveProperty()
객체에 해당 key : value 값이 있는지 검사한다.
test("find user property", async () => {
const user = {
id : 1,
name : "Leanne Graham"
}
expect(user).toHaveProperty("id", 1); // { id : 1 } 이 user 객체에 있느냐? -> true
expect(user).toHaveProperty("name", "Leanne Graham");
});
toBeCalledTimes() / toBeCalledWith()
toBeCalledTimes() : 함수가 몇번 호출되었는지 검증
toBeCalledWith() : 함수가 설정한 인자로 호출 되었는지 검증
drink("aa");
drink("aa");
expect(drink).toHaveBeenCalledTimes(2); // drink함수가 2번 호출?
expect(drink).toHaveBeenCalledWith("aa"); // drink함수가 "aa" 문자열 인자로 호출?
toReturn() / toHaveReturned()
함수가 오류없이 반환되는지 테스트
toReturnTimes() / toHaveReturnedTimes()
함수가 지정한 횟수만큼 오류없이 반환되는지 테스트하는데 호출 횟수는 포함하지 않는다.
test('drink returns twice', () => {
const drink = jest.fn(() => true);
drink();
drink();
expect(drink).toHaveReturnedTimes(2); // 오류없이 리턴을 무사히 마친 횟수? -> 2
});
toReturnWith() / toHaveReturnedWith(value)
함수가 지정한 값을 반환하는지 테스트
test('drink returns La Croix', () => {
const beverage = {name: 'La Croix'};
const drink = jest.fn(beverage => beverage.name);
drink(beverage);
expect(drink).toHaveReturnedWith('La Croix'); // drink(beverage) 함수 결과가 'La Croix' 문자열을 반환하는지?
});
이 글이 좋으셨다면 구독 & 좋아요
여러분의 구독과 좋아요는
저자에게 큰 힘이 됩니다.