아래는 필자가 실제 사용하고 있는 미들웨어 로직입니다.
해당 함수를 단위 테스트하려고 합니다.
// test.middleware.ts
import CError, { ERROR_MESSAGE } from "@utils/error";
import HTTP_STATUS_CODE from "@utils/http-status-code";
import { NextFunction, Request, Response } from "express";
import { validationResult } from "express-validator";
/**
* @description 파라미터 유효성 검사하는 미들웨어
*/
export default async (req: Request, res: Response, next: NextFunction) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
const error = new CError(ERROR_MESSAGE.INVALID_VALUE, HTTP_STATUS_CODE.INVALID_VALUE);
res.error(error);
return;
}
next();
};
함수 안에 사용하고 있는 validationResult
라는 함수가 있습니다.
함수의 반환값에 따라 수행되는 작업이 달라져요..
테스트에선 validationResult
함수를 호출하지 않고 테스트를 하려고 합니다.
if 조건의 !errors.isEmpty()
값을 다르게 해야 하는데, 어떻게 해야할까요?😯
jest.mock
함수는 자동으로 모듈을 mocking하도록 도와줍니다.
💡 Jest 공식 문서(mocking module)를 참고했어요 :)
문서의 axios
예시처럼, 필자도 비슷하게 만들어볼게요 ㅎㅎ
에러가 발생하네요.. 타입은 any
, validatorResult
함수의 mockReturnValue
라는 속성은 없다고 합니다.
어찌된 일일까요..?
Type checking이 제대로 되지 않아 생기는 문제였습니다.
Jest에서는 jest.mocked
함수를 제공하여, 객체에 jest의 mock function들을 래핑해 타입을 보장해줍니다.
💡 Jest 공식 문서(jest mocked source options)를 참고했어요 :)
코드를 조금 수정해보겠습니다.
import testMiddleware from "@middlewares/test.middleware";
import { Request, Response } from "express";
import { Result, ValidationError, validationResult } from "express-validator";
jest.mock("express-validator"); // 자동으로 mocking을 해주지만
const mockedValidationResult = jest.mocked(validationResult); // 해당 함수를 사용해 jest mocking function의 사용할 수 있도록 타입 래핑까지 처리해줌
describe("validator middleware test :)", () => {
const req = {} as Request;
const res = {
error: jest.fn(),
} as unknown as Response;
const next = jest.fn();
test("error handler", () => {
mockedValidationResult.mockReturnValue({
isEmpty: () => false,
} as Result<ValidationError>); // 실제 사용된 부분
testMiddleware(req, res, next);
expect(res.error).toBeCalledTimes(1);
});
});
이제 에러없이 동작합니다!😛
import testMiddleware from "@middlewares/test.middleware";
import { Request, Response } from "express";
import { Result, ValidationError, validationResult } from "express-validator";
jest.mock("express-validator");
const mockedValidationResult = jest.mocked(validationResult); // jest 함수
describe("validator middleware test :)", () => {
const req = {} as Request;
const res = {
error: jest.fn(),
} as unknown as Response;
const next = jest.fn();
test("error handler", () => {
mockedValidationResult.mockReturnValue({
isEmpty: () => false,
} as Result<ValidationError>);
testMiddleware(req, res, next);
expect(res.error).toBeCalledTimes(1);
});
test("next", () => {
mockedValidationResult.mockReturnValue({
isEmpty: () => true,
} as Result<ValidationError>);
testMiddleware(req, res, next);
expect(next).toBeCalledTimes(1);
});
});