Jest로 단위 테스트 코드를 구현할 때 자주 사용되는 API
describe
describe('User Service', () => {
// 여기서 User Service와 관련된 테스트 케이스를 작성합니다.
});
테스트할 대상에 대한 설명을 작성하는 데 사용한다. 그룹화된 테스트 케이스를 설명하여 어떤 기능이나 모듈을 테스트하고 있는지 명확하게 나타낸다.
하나의 테스트 케이스를 test()라고 한다면 describe()는 여러 개의 테스트 케이스를 하나의 그룹으로 묶어주는 역할을 한다.
it
it('should create a new user', () => {
// 새로운 사용자가 생성되는지 테스트하는 코드
});
개별적인 테스트 케이스를 나타내며, 특정 상황이나 조건에서 코드가 어떻게 동작하는지 테스트한다. 주로 "should"와 같은 형식으로 테스트의 기대 결과를 설명한다.
Expect
test('adds 1 + 2 to equal 3', () => {
expect(1 + 2).toBe(3); // 1 + 2의 결과가 3인지 테스트
});
test('object assignment', () => {
const data = { one: 1 };
data['two'] = 2;
expect(data).toEqual({ one: 1, two: 2 }); // 객체의 속성 값이 일치하는지 테스트
});
테스트할 대상을 넣는 API. expect()에는 주로 테스트 입력 값 또는 기대 값을 넣는다.
beforeAll vs beforeEach
beforeAll(() => {
// 모든 테스트 전에 한 번 실행됩니다.
initializeDatabase();
});
beforeEach(() => {
// 각 테스트 전에 실행됩니다.
resetDatabase();
});
세팅을 매 테스트마다 할 것인지 또는 전체 테스트에서 한 번만 해도 되는지의 차이이다.
예를 들어, mocking 한 respository 같은 경우에는 createAccount 테스트에도 사용할 수가 있고, seeProfile, editProfile 테스트하는 경우에도 모두 사용가능한데, 매번 사용 횟수나 들어간 변수들을 초기화하지 않으면 테스트가 꼬일 수밖에 없다. 그래서 user.service를 테스트할 때에는 beforeAll이 아니라 beforeEach로 사용하면 된다.
beforeAll 테스트가 실행되기 전에 딱 한 번 설정 작업을 수행한다. 예를 들어, 테스트 환경을 설정하거나 공통 리소스를 준비할 때 사용된다.
beforeEach: 각 테스트가 실행되기 전에 설정 작업을 수행한다. 예를 들어, 매 테스트마다 초기 상태를 보장해야 하는 경우, 모의 객체를 재설정하거나 데이터를 초기화할 때 사용된다.
mockResolvedValueOnce
const mockFindUser = jest.fn();
mockFindUser.mockResolvedValueOnce({ id: 1, name: 'John Doe' });
it('should return user by id', async () => {
const user = await mockFindUser(1);
expect(user.name).toBe('John Doe');
});
한 번 호출될 때 특정 값을 resolve하는 Promise를 반환하도록 모의 함수(Mock Function)를 설정한다. 실제 데이터베이스와 상관없이 특정 값을 반환하게 할 때 사용된다.
어떤 경우라도 db와는 관계 없이 값을 resolve로 넘겨준다는 뜻이다.
mockReturnValueOnce
const mockGetUser = jest.fn();
mockGetUser.mockReturnValueOnce({ id: 1, name: 'Jane Doe' });
it('should return user object', () => {
const user = mockGetUser();
expect(user.name).toBe('Jane Doe');
});
모의 함수가 한 번 호출될 때 지정된 값을 반환하도록 설정한다. Promise가 아닌 단순한 객체나 값일 경우에 사용된다. TypeORM repository에서 Promise로 리턴을 하는 것이 아니라, 엔티티 객체를 리턴한다.
mockResolvedValue
const mockSaveUser = jest.fn();
mockSaveUser.mockResolvedValue({ id: 2, name: 'Alice' });
it('should save user to database', async () => {
const user = await mockSaveUser();
expect(user.name).toBe('Alice');
});
모의 함수가 호출될 때마다 특정 값을 resolve 하는 Promise를 반환한다. 예를 들어, 데이터베이스에 성공적으로 저장된 값을 흉내내는 데 사용된다.
toHaveBeenCalledTimes
const mockFunction = jest.fn();
mockFunction();
mockFunction();
it('should call the function twice', () => {
expect(mockFunction).toHaveBeenCalledTimes(2);
});
특정 함수가 기대한 횟수만큼 호출되었는지 검증한다. 함수 호출 횟수가 올바른지 확인할 때 사용된다.
toHaveBeenCalledWith
const mockFunction = jest.fn();
mockFunction('argument1', 'argument2');
it('should call the function with correct arguments', () => {
expect(mockFunction).toHaveBeenCalledWith('argument1', 'argument2');
});
특정 함수가 호출될 때 전달된 인수가 예상한 값과 일치하는지 검증한다. 함수가 올바른 인수로 호출되었는지 확인할 때 사용된다.
toMatchObject
const user = { id: 3, name: 'Bob', age: 30 };
it('should match the object properties', () => {
expect(user).toMatchObject({ name: 'Bob', age: 30 });
});
객체의 일부 속성이 기대한 값과 일치하는지 확인한다. 테스트 대상의 결과가 원하는 형식과 부분적으로 일치하는지 확인할 때 사용된다.
mockResolvedValue, mockReturnValue 사용 예시
// user.service.ts
async createAccount({
email,
password,
role,
}: CreateAccountInput): Promise<UserProfileOutput> {
...
// 작성한 이메일이 존재하지 않는다면 작성한 계정 저장하기
const user = await this.user.save(
this.user.create({ email, password, role }),
);
}
// user.service.spec.ts
it("should create a new user", async () => {
userRepository.create.mockReturnValue(createAccountArgs);
userRepository.save.mockReturnValue(createAccountArgs);
...
});
- mockReturnValue: userRepository.create는 동기 메소드이므로 mockReturnValue를 사용하여 객체를 반환하도록 설정한다.
- mockResolvedValue: userRepository.save는 비동기 메소드이므로 mockResolvedValue를 사용하여 Promise가 resolve 될 때 객체를 반환하도록 설정한다.
'Frontend > Jest' 카테고리의 다른 글
Mocking, 가짜 레파지토리, 함수 만들기 (0) | 2024.08.01 |
---|---|
Jest 란 (0) | 2024.08.01 |