로그인 상태일 때와 비로그인 상태일 때를 구분하여 테스트를 진행하기 위해 테스트 코드를 작성한 후, 처리하려 했으나 제대로 작성하지 않았다.
처음에는 로그인 상태에서만 테스트를 진행했다.
아래 방식을 이용하여 next-auth에서 useSession 훅에 접근할 수 있도록 처리했다.
jest.mock("next-auth/react", () => {
const originalModule = jest.requireActual("next-auth/react"); // next-auth/react 모듈을 로드한다.
const mockSession = {
expires: new Date(Date.now() + 2 * 86400).toISOString(),
user: { username: "admin" },
}; // 로그인 상태를 테스트하기 위해, 로그인 세션 정보 정의
return {
__esModule: true, // ES 모듈 호환을 위함
...originalModule, // 기존 모듈의 내보내기를 보존하면서 리턴한다.
useSession: jest.fn(() => {
return { data: mockSession, status: "authenticated" }; // useSession을 모킹하고, 로그인 된 상태인 세션 데이터를 반환하도록
}),
};
});
그리고 이후에 로그인 되지 않은 상태를 테스트하기 위헤, next-auth/react 라이브러리를 다시 모킹하려 했으나, 같은 모듈을 한 번 이상 모킹할 경우, 마지막에 지정한 모킹을 설정만 유효해지기 때문에 하나의 테스트에서 동일한 모듈은 한 번 이상 할 수 없었다.
따라서 내가 하려던 로그인 상태, 비로그인 상태의 테스트를 수행할 수 없었다.
우선 테스트를 다시 하나의 페이지 단위로 묶고, 그 하위에 로그인 상태, 비로그인 상태를 체크할 수 있도록 describe로 정의했다.
describe("랜딩 페이지 테스트", () => {
describe("로그인 상태", () => {});
describe("비로그인 상태", () => {});
});
그 뒤, next-auth의 useSession 훅에 접근할 수 있도록 하기 위하여 해당 모듈을 mocking한다.
그리고 useSession을 사용한 로직을 검증할 수 있도록 useSession 훅을 jest.fn을 사용하여 mock function을 생성한다.
jest.mock("next-auth/react", () => ({
__esModule: true,
useSession: jest.fn(),
}));
jest.fn은 기본적으로 비어있는 함수이기 때문에 내부 로직을 구현해 주어야 한다. 그것을 처리하기 위한 것이 mockImplementation
이다.
mockImplementation를 이용하여 각 상태에 따른 테스트 실행 이전에 모킹된 useSession에 로그인 상태를 전달해 준다.
로그인 상태일 때
beforeEach(() => {
useSession.mockImplementation(() => ({
data: {
expires: new Date(Date.now() + 2 * 86400).toISOString(),
user: { username: "admin" },
},
status: "authenticated",
}));
});
// 비로그인 상태일 때
beforeEach(() => {
useSession.mockImplementation(() => ({
data: undefined,
status: "unauthenticated",
}));
});
그리고 각 테스트(로그인 상태와 비로그인 상태) 이전에 mocking function들을 초기화 해주어야 한다.
beforeEach(() => {
jest.resetAllMocks();
});
이렇게 초기화를 해주는 이유는, 각 테스트 케이스가 다른 테스크 케이스에 미치는 영향을 주지 않도록 처리하여, 결과의 일관성을 보장할 수 있기 때문이다.
이렇게 하면 로그인 상태에 따른 테스트로직을 작성할 수 있다.