오늘 읽은 범위
4장 목 객체
책에서 기억하고 싶은 내용을 써보세요.
목 객체 유형
- 스텁
- 주로 대역으로 사용한다.
- 의존중인 컴포넌트에 테스트하기 어려운부분이 있을 때 사용한다. (ex. 웹 api 호출)
- 스파이
- 주로 기록하는 용도로 사용한다.
- 테스트 대상 외부의 출력을 검증할 때 사용한다. (ex. 콜백 함수)
목 모듈을 활용한 스텁
jest.mock(modulePath, factoryFn)
- 함수가 들어있는 모듈을 통째로 mocking
- jest.mock(테스트할 모듈, 어떻게 mock할지 정의하는 함수)
jest.mock('./greet', () => {
return {
greet: jest.fn(() => 'Hi!'),
bye: jest.fn(() => 'See ya!'),
};
});
import { greet, bye } from './greet';
test('custom mock with factory', () => {
expect(greet('Alice')).toBe('Hi!');
expect(bye('Bob')).toBe('See ya!');
});웹 API 스텁
jest.spyOn(object, methodName)
- jest.spyOn(테스트할 객체, 테스트할 함수 이름)
- mockResolvedValueOnce() : 비동기 모의 함수가 resovled일때 지정한 값을 한번만 지정
- mockRejectedValueOnce() : 비동기 모의 함수가 rejected일때 지정한 값을 한번만 지정
test('성공 시', async () => {
jest.spyOn(Fetchers, "getMyProfile").mockResolvedValueOnce({
name: "jessie",
});
await expect(getGreet()).resolves.toBe("Hello, jessie!");
})
test('실패 시', async () => {
jest.spyOn(Fetchers, "getMyProfile").mockRejectedValueOnce(httpError);
await expect(getGreet()).rejects.toMatchObject({
err : {message: "internal server error"},
})
})목 함수를 사용하는 스파이
- toBeCalled() : 실행됐는지 검증
- toHaveBeenCalledTimes() : 실행 횟수 검증
- toHaveBeenCalledWith() : 실행 시 인수 검증
test("목 함수는 실행 시 인수를 기록한다.", () => {
const mockFn = jest.fn();
function greet(message: string) {
mockFn(message);
}
greet("hello");
expect(mockFn).toHaveBeenCalledWith("hello");
})현재 시각에 의존하는 테스트
- 테스트 결과가 실행 시각에 의존하게 되는 경우, 테스트 실행 환경의 현재 시각을 고정하면 언제라도 같은 실행 결과를 얻을 수 있다.
궁금한 내용이 있거나, 잘 이해되지 않는 내용이 있다면 적어보세요.
- 스텁과 스파이의 개념 및 비교
| 구분 | 스텁 | 스파이 |
|---|---|---|
| 목적 | 미리 정해둔 값을 돌려주기만 한다. | 호출 기록이나 파라미터를 기억하고 필요하면 동작도 정의 할 수 있다. |
| 관심사 | 결과값 | 호출 정보와 결과값 |
| 테스트 용도 | 특정 상황을 시뮬레이션 | 호출 여부, 횟수, 전달된 값 검증 |
- mocking이 적용되는 이유
jest.spyOn(Fetchers, "getMyArticles")는Fetchers객체의getMyArticles프로퍼티 자체를 스파이/목 함수로 갈아끼우는 사이드 이펙트를 일으킨다. 이미 전역적으로 바꿔치기된 상태이기 때문에 굳이 mockGetMyArticles 호출의 리턴값을 변수에 안담아도 전부 목 버전을 쓰게 되는 것.
function mockGetMyArticles(status = 200) {
if (status > 299) {
return jest
.spyOn(Fetchers, "getMyArticles")
.mockRejectedValueOnce(httpError);
}
return jest
.spyOn(Fetchers, "getMyArticles")
.mockResolvedValueOnce(getMyArticlesData);
}
test("지정한 태그를 포함한 기사가 한 건도 없으면 null을 반환한다", async () => {
mockGetMyArticles();
const data = await getMyArticleLinksByCategory("playwright");
expect(data).toBeNull();
});