티스토리 뷰
유닛 테스트 코드 오류 예시 설명
repositories
1. User Repository Unit Test
테스트하려는 테스트스위트 4가지가 정의 되어 있고 나머지는 통과가 됬는데
updateToken Method테스트에서 실패를 했다라는걸 간략하게 보여줌
2. User Repository Unit Test > updateToken Method
해당 테스트에서 에러가 난걸 강조해서 보여준다.
3. expect(received).toBe(expected)
둘을 서로 비교해주는 메서드인걸 주석으로 알려주며 아래의 예상값과 현재값이 담겨있다.
Expected의 예상값은 "upload refreshToken"
Received의 현재값은 {}
즉, 실패한 원인을 알려주고 어느 위치에서 에러가 낫는지도 친절하게 알려준다.
이제 그부분을 돌아가보자
expect(received).toBe(expected)부분은 단순히 값을 받아오고 비교하는 곳이기 때문에 그 위로 올라가서 찾아봐야한다.
가장 중요한 부분은
const user = usersRepositories.updateToken()이다.
실제 메서드를 따라가보면
updateToken 메서드는 비동기 함수이며 반환되는 값은 프로미스이다.
즉, 비동기 작업이 끝날때까지 기다려야 하는데 테스트 코드를 보면 기다림 없이 동기로 작동하고 있다.
그러므로 결곡 빈 객체를 반환했던것이다.
이를 다시 await를 사용하여 비동기작업으로 바꿔주면
모든 테스트가 통과한걸 확인 할 수 있다.
service
로그인테스트
1. 받아온 값들이 예상한 값과 다르다.
access토큰이랑 refresh토큰을 만들어 주겠다고 생각하였으나
생각해보니 테스트부분과 실제 로직부분에 따로 토큰을 만들면 서로 다른 토큰이기 때문에 실패가 뜬다.
그래서 expect에서 사용하는 메서드를 한번 확인해 보았다.
모의 함수가 한 번 이상 성공적으로 반환되었는지(즉, 오류가 발생하지 않았는지) 테스트하는 데 사용하는 matcher였다.
이걸 사용해보면 되겠다 해서 사용을 해봤다.
성공적으로 리턴한다면 값이 다 들어있는거라 괜찮을 줄 알았지만 아니였나보다
다른걸 찾아봤다.
변수가 정의되지 않았는지 확인하는 데 사용한다고 한다.
그러다가 user라는 변수에 리턴값이 들어간다 라는 생각을 해봤다.
만약 user가 undefined가 아니라면 테스트가 통과되지 않을까 라는 생각을 했다.
user변수에는 토큰과 같은 값들이 들어있으니까 시도해 볼만하다고 생각했다.
통과 한것을 볼수가 있다.
하지만 뭔가 찝찝한 느낌이 든다. 이렇게 테스트 하는게 맞는지에 대해.. 다른 방법을 찾아봐야겠다..
내 정보 조회 테스트
공식사이트를 들어가보니 toBe()는 엄격한 (strict) 동등성을 비교하면서
두 객체가 메모리상의 같은 위치를 참조하는지 확인 객체의 내용이 완전히 동일한 경우에만 통과된다고 한다.
또한 단순한 값이나 원시 데이터 유형을 비교할 때 주로 toBe를 쓴다고 한다.
하지만 위 expected값은 객체이고 속성과 값을 비교하므로 다른 메서드를 찾아야한다.
toStrictEqual() : 구조와 유형이 동일한지 테스트를 하기 위해 사용하는 메서드
두 객체가 메모리상 다른 위치를 참조하더라도 객체의 모든 속성과 속성 값이 일치하면 통과 할수가 있다.
또한 객체나 배열과 같은 복합적인 데이터 유형을 비교할 때 toStrictEqual()메서드를 주로 사용한다고 한다.
이렇게 수정을 한뒤 테스트 해보니
모든 테스트가 통과한걸 확인 할 수 있다.
controller
회원가입테스트
// 회원가입 테스트
test("signUp Method by success", async () => {
const createUserRequestBody = {
email: "email_Success",
password: "password_Success",
passwordCheck: "passwordCheck_Success",
userName: "userName_Success",
};
mockRequest.body = createUserRequestBody;
const createUserReturnValue = {
id: 1,
email: "email_Success",
userName: "userName_Success",
};
mockUsersService.createUser.mockReturnValue(createUserReturnValue);
await usersController.signUp(mockRequest, mockResponse, mockNext);
expect(mockUsersService.createUser).toHaveBeenCalledWith(
createUserRequestBody.email,
createUserRequestBody.password,
createUserRequestBody.userName
);
expect(mockUsersService.createUser).toHaveBeenCalledTimes(1);
expect(mockResponse.status).toHaveBeenCalledTimes(1);
expect(mockResponse.status).toHaveBeenCalledWith(201);
expect(mockResponse.json).toHaveBeenCalledWith({
data: createUserReturnValue,
});
});
위 부분에서
함수가 해당 매개변수로 호출되었는지 확인하는 메서드인데 위 실패 사항을 보면 함수자체가 없는것처럼 보인다.
어디서 문제인지 의존성 주입을 잘못했는지 부터 확인을 했다.
의존성은 문제가 없었다
근데
????
????
설마 이 유효성 검사때문에 그런건가 싶어
바꿔주고 테스트를 실행하니
바로 성공을 했다.
로그인테스트
로그인 테스트함에 있어서 역시나 바로 실패를 했다
하지만 이제는 길이 좀 보이는것같다
undefined가 뜨는것은 분명또 catch문으로 빠져서 에러가 나왔을것같다
콘솔을 찍어서 확인해 보니
에러구문으로 들어갔다.
이제 에러를 한번 잡아보자
err.message로 찍고 보니 쿠키를 응답에 넣지 못한다고한다.
쿠키파서가 없어서 뜨는 문제인거같다.
근데 이건 app.js에서 퍼지는건데 controller에서 다시 모듈을 설치해줘야하나?라는 생각이 들었다.
그러면 req, body처럼 적용시켜주면 되는거 아닌가?
이렇게 쿠키를 스파이로 지정해줬다.
일반적으로 테스트코드에서 직접적으로 쿠키 값을 설정하는 것은 까다롭기 때문에 쿠키와 같은 외부 의존성을 가지는 부분을 목(mock)이나 스파이(spy)를 사용하여 대체한다고 한다.
이것을 사용하여 의존성을 격리시키고 테스트코드의 독성을 유지할수 있게 된다.
또한 이처럼 코드를 작성하여 res.cookie가 호출되었는지 확인하고 올바른 쿠키값이 설정되어있는지 확인도 할수가 있다.
테스트를 해보면
테스트들을 통과한걸 볼수 있다.
그렇게 유저 관련 부분 테스트 코드 테스트 완료를 햇다.
느낀점
테스트 코드는 정말 a-z까지 하나하나 다 살펴봐야 하는걸 느꼇다.
의미도 모르는 곳에서 에러가 나는것도 정말 많았고 시간도 정말 오래 걸리는 일이였다.
또한 여기서 의존성이 서로 겹쳐있으면 테스트 하기에도 정말 곤란하다는걸 알았다
토큰같은 경우 다음 테스트를 한다고 하면 그전에 토큰들을 다 분리 시켜놔야겠다.
변수명 리턴값도 하나하나 다 신경써야하고 머릿속으로 로직을 미리 짜둔다음 그 경우의 수를 다 검사하는것 같다
테스트 코드를 할때는 return 되는 값조차 하나하나 테스트를 해야하니 확인하기가 정말 어려운것 같다.
다음엔 테스트코드하기 좋은 코드를 생각하면서 설계한다음 로직을 짜보도록 해야겠다
'개발일지 > 문제 해결' 카테고리의 다른 글
[문제해결] Route.get() requires a callback function but got a [object Undefined] (1) | 2024.02.27 |
---|---|
[문제 해결] AWS S3 TypeError: this.client.send is not a function (0) | 2024.02.14 |
[문제 해결] prisma : error 타입에러 (0) | 2024.02.09 |
[문제 해결] SyntaxError 엄격모드에 대해서.. (1) | 2024.01.31 |
[문제해결] node server.js 실행 시 오류 발생 (0) | 2024.01.25 |