축구팀 관리 프로젝트 36일차 - jwt 모의함수 구현 오류
테스트 코드 작성 중 발견한 jwt 모의함수 구현 오류를 어떻게 해결했는지 소개하겠습니다.
jwt 모의함수 구현 오류
문제발견
문제는 아래 코드에서 시작됐습니다.
jest.spyOn(jwtService, 'verify').mockResolvedValue({ id: 1 });을 사용하여 Jest에서 jwtService.verify를 모의하려고 할 때, TypeScript에서 '{ id: number; }' 형식의 인수는 'never' 형식의 매개 변수에 할당될 수 없다는 오류가 발생했습니다.
오류 원인 분석
이 오류는 TypeScript가 모의 함수에서 정확한 타입을 추론할 수 없어서 발생했습니다. mockResolvedValue는 인수로 전달된 값의 타입을 추론하기 때문에, { id: 1 }이라는 객체의 타입을 정확히 알 수 없어서 오류가 발생했습니다.
시도한 방법들
NestJS의 JwtService에서 verify 메서드의 반환값 타입을 찾으려면, 먼저 @nestjs/jwt 패키지의 공식 문서나 소스 코드를 확인해야 한다고 하는 글을 보고 바로 찾아봤습니다.
확인해보니 verify는 아래처럼 되어 있었습니다.
verify<T extends object = any>(token: string, options?: JwtVerifyOptions): T;
제네릭 타입 T extends object = any를 사용중 이었습니다.
이는 verify 메서드가 어떤 객체 타입을 반환할지를 호출 시점에서 결정할 수 있음을 의미했습니다. 따라서, verify 메서드의 반환값 타입은 호출하는 측에서 지정한 제네릭 타입에 의해 결정된다는 사실을 알게 되었습니다.
그래서 타입을 지정하면 되는건가 싶어 아래처럼 시도해보았습니다.
jest.spyOn(jwtService, 'verify').mockResolvedValue<{ id: number }>({ id: 1 });
jest.spyOn(jwtService, 'verify').mockResolvedValue<{ id: number }>({ id: 1 } as { id: number });
const mockPayload: { id: number } = { id: 1 };
jest.spyOn(jwtService, 'verify').mockResolvedValue(mockPayload);
그래도 오류는 동일하게 나타났습니다.
다시 여러 자료를 찾아보다가 이 블로그를 보게 되었습니다.
여기서 JwtService를 모킹할 때 보지 못했던 방식을 발견할 수 있었습니다.
- (3) 프로젝트에서 사용하는 외부 패키지인 JwtService 모킹(2): useValue 활용하여
JwtService의 하위 메소드인 signAsync의 return 값을 테스트 환경에 맞춰서 모킹
{
provide: JwtService,
useValue: {
signAsync: (payload, option) => {
return 'sample token';
},
},
},
JwtService의 하위 메소드 중에 signAsync를 활용하는 코드였습니다. 이 방식에 대해 더 찾아보니 아래와 같은 기능을 하고 있었습니다.
signAsync는 일반적으로 JWT(JSON Web Token)를 생성하기 위해 사용되는 메서드입니다.
JWT는 인증 및 정보 교환을 위해 사용되는 토큰 기반의 인증 방식 중 하나입니다. signAsync 메서드는 주로 사용자 인증 후 토큰을 생성하고 반환하는 데에 사용됩니다.
보통 signAsync 메서드는 비동기적으로 작동하여 비밀 키를 사용하여 페이로드를 서명하고 토큰을 생성합니다. 생성된 토큰은 사용자의 인증 정보를 포함하며, 클라이언트와 서버 간의 통신에 사용될 수 있습니다.
모의(mock) 환경에서 signAsync 메서드를 모의하려면, 예를 들어, 테스트에서 실제로 토큰을 생성하지 않고도 모의된 토큰을 반환할 수 있습니다.
이렇게 함으로써 실제 토큰 생성 로직에 의존하지 않고도 테스트를 수행할 수 있습니다. 따라서 signAsync 메서드를 모의(mock)하기 위해 모의(mock) 함수를 사용하여 원하는 토큰을 반환하도록 설정할 수 있습니다. 이렇게 하면 테스트를 보다 간편하게 수행할 수 있습니다.
모의 환경에서 signAsync 메서드 모의시 장점은 실제 토큰 생성하지 않아도 모의 토큰을 반환할 수 있다는 점이 있었습니다. 원래 구현하려던 jest.spyOn(jwtService, 'verify').mockResolvedValue({ id: 1 }); 코드도 결국 토큰 발급이 정상적으로 되는지 확인하기 위함이니까 이 방식을 사용해도 되겠다고 판단했습니다.
문제 해결 방법
위 자료를 참고하여 아래와 같은 코드로 수정할 수 있었습니다.
jest.spyOn(jwtService, 'verify').mockImplementation(async (token: string) => {
const payload = await jwtService.signAsync({ id: 1 });
return payload;
});
여기서 mockImplementation을 사용하였는데 이 메서드는 Jest에서 모의(mock) 함수의 동작을 직접 구현할 때 사용합니다.이 메서드를 사용하면 실제 함수를 모의하여 원하는 동작을 시뮬레이션 가능한 특징이 있습니다. 이를 활용하여 토큰 생성하는 코드를 작성하였습니다.
▼ 이전 진행한 프로젝트들 ▼
'내일배움캠프 > 축구팀 관리 프로젝트' 카테고리의 다른 글
축구팀 관리 프로젝트 38일차 - soft delete된 팀 멤버가 조회되는 오류 (0) | 2024.02.19 |
---|---|
축구팀 관리 프로젝트 37일차 - 목표 테스트 커버리지 80% 중 56% 달성 (0) | 2024.02.18 |
축구팀 관리 프로젝트 34일차 - 유저테스트 시작, 취업 준비 (0) | 2024.02.14 |
축구팀 관리 프로젝트 33일차 - 프로젝트 유저 테스트 준비 (0) | 2024.02.13 |
축구팀 관리 프로젝트 27일차 - 경기 생성 및 결과 테스트 코드 작성 (0) | 2024.02.08 |