Testing

[TDD] node-mocks-http를 활용한 request, response 객체 생성

kyuuuun 2023. 12. 29. 19:57
728x90

 

node-mocks-http 란?

핵심만 말하자면 Express.js, Next.js 애플리케이션에서 라우팅 함수를 테스트 하기 위해 http 객체(request, response)를 생성할때 사용한다. 실제로 restAPI를 통해 http 통신을 할때 request 와 response 객체를 정말 많이 마주하지만 이를 테스트하기 위해 http 객체를 모킹하는 방법이 번거롭고 까다롭다. 하지만 node-mocks-http를 사용하여 간단하게 express/next.js의 request, response mock 객체를 생성할수있다. 글로 설명하는 하는 것 보다 아래 설치 및 사용법에서 예시 코드와 함께 정리해보려 한다.


node-mocks-http 설치 및 사용법

1. node-mocks-http 설치

npm i node-mocks-http --save-dev

우선 node-mocks 를위 명령어를 프로젝트 경로에서 실행시켜 설치할 수 있다. 

 

2. 테스트 코드 작성

아래의 예시 코드는 mongoose 모듈을 활용하여 express.js 어플리케이션에서 mongo DB에 데이터를 적재하는 과정을 테스트하기 위한 테스트 코드의 일부이다.

/* /test/unit/products.test.js  */
const productModel = require('../../models/Product');
const productController = require('../../controller/products');
const httpMocks = require('node-mocks-http');

let req, res, next;

// 다른 테스트 케이스에서도 사용할 수 있도록 불필요한 반복을 줄이기 위해 beforeEach 사용
beforeEach(() => {
  req = httpMocks.createRequest();
  res = httpMocks.createResponse();
  next = jest.fn();
});

describe('Product Controller Create', () => {
  beforeEach(() => {
    req.body = newProduct;
  });
  //expect와 matcher를 통해서 DB에 데이터가 되는 부분 테스트
  it('should call ProductModel.create', async () => {
    await productController.createProduct(req, res, next);
    expect(productModel.create).toBeCalledWith(newProduct);
  });
});

위와 같이 httpMocks 를 가져와서 선언한 뒤 createRequest와 createResponse 함수를 사용하여 request 객체와 response 객체를 생성한다. 이 후 테스트 코드를 작성하고 createProduct에 req, res 를 인자로 넣어준 뒤 expect와 matcher를 사용하여productModel.create 함수 호출시 newProduct 객체가 같이 호출됐는지 테스트를 진행할 수 있다. 

단, 테스트 코드 작성후 이를 기반으로 실제코드 작성 후 테스트를 진행해야 한다.

 

3. 실제 코드 작성

테스트 코드를 작성했다면 테스트를 통과하기 위한 실제 코드를 아래와 같이 작성한다.

/* /controller/products.js */
const productModel = require('../models/Product');

exports.createProduct = async (req, res, next) => {
  try {
    const createdProduct = await productModel.create(req.body);
    res.status(201).json(createdProduct);
  } catch (error) {
    next(error);
  }
};

 

테스트 코드에 작성된 대로 productModel.create 호출시 newProduct가 인자로 함께 전달될 수 있도록 request 객체로 전달될 req인자의 body 값을 같이 넣어준다.   

 

▪︎ 참고

node-mocks-http의 response객체는 테스트 검증을 위한 아래와 같은 여러가지 함수를 제공하는데 각 경우에 맞게 유용하게 사용할 수 있다.

//res.status(201).send()에서 send()나 json()과 같이 추가적인 결과값이 전달되고 있는지 확인할 수 있다. 전달된다면 true
expect(res._isEndCalled()).toBeTruthy();

//res.status(201).json(createdProduct)과 같이 response값이 JSON 형식인지 true/false
expect(res._isJSON()).toBeTruthy();

//response에 담긴 JSON 타입의 결과 데이터를 확인할 수 있다.
expect(res._getJSONData()).toStrictEqual([JSONData]);

//response 상태코드 값을 확인할 수 있다.
expect(res.statusCode).toBe(201);

//response 인코딩 형식이 UTF-8 인지 true/fasle
expect(res._isUTF8()).toBeTruthy();