순서

1. 데이터를 저장할 때 에러가 나는 부분을 파악

2. 에러에 해당되는 부분에 대한 단위 테스트 작성

3. 테스트에 대응하는 실제 코드 작성

 

(테스트 상황) 비동기 요청에 대한 에러발생

비동기 요청에 대한 결과값

  • 성공 : Promise.resolve(value)
  • 에러 : Promise.reject(reason) 

에러 상황 구현

1. 데이터베이스에서 처리하는 부분은 문제가 없다.

2. 비동기 요청시 에러 발생

// express + jest
const productController = require("../../controller/products");
const productModel = require("../../models/Product");
const httpMocks = require('node-mocks-http');
const newProduct = require('../data/new-product.json');

productModel.create = jest.fn();

let req, res, next;
beforeEach(() =>{
    req = httpMocks.createRequest();
    res = httpMocks.createResponse();
    next = jest.fn(); // 미들웨어 함수를 목 함수로 대체
})

describe('Products Controller', ()=>{
    beforeEach(() =>{
        req.body = newProduct;
    });
    
    it('Should handle errors', async () => {
        const errorMessage = {message: 'Description property missing'};
        const rejectedPromise = Promise.reject(errorMessage);
        productModel.create.mockReturnValue(rejectedPromise) // 에러상황을 생성
        await productController.createProduct(req, res, next);
        expect(next).toBeCalledWith(errorMessage);
     });
});

 

- next 로 에러를 처리하는 이유 : express에서 비동기 요청에서 발생하는 에러를 받으면 서버가 망가진다. 이 에러를 next를 이용하면 처리가 가능하다.

 

테스트에 대응하는 실제 코드 작성

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); // next 에 에러값을 넣어주면 비동기 요청에 대한 에러를 잘처리 할 수 있는 곳으로 보내준다.
    }
};

jest 를 적용하기 위해서 필요한 설정

1. Jest 설치 확인

npm install jest --save-dev

 

2. pacakge.json 에 있는 테스트 스크립트 변경/추가

 "scripts": {
    "test": "jest" 
  },

 

3. 기본적인 설정 파일을 생성 : jest.config.js 생성

$ npx jest --init

   - Would you like to use Typescript for the configuration file?   → No 선택

Given-When-Then은 주로 BDD(Behavior-Driven Development)에서 사용되는 테스트 시나리오 작성 패턴으로 테스트 의도를 쉽게 공유하고 이해할 수 있게 해줍니다.

 

  • Given (상황 설정):
    • 테스트의 시작 상태 또는 전제 조건을 설정합니다.
    • 애플리케이션이 어떤 상태에 있는지를 설명합니다.
  • When (행동):
    • 테스트하려는 특정 행동이나 이벤트를 정의합니다.
    • 애플리케이션이 처리해야 할 동작을 설명합니다.
  • Then (결과):
    • 행동이 발생한 후 기대하는 결과를 정의합니다.
    • 애플리케이션이 어떻게 반응해야 하는지를 설명합니다.
  • 예시
    • (Given) 사용자가 로그인하지 않은 상태에서 시작한다.
    • (When) 사용자가 로그인 버튼을 클릭한다.
    • (Then) 사용자가 대시보드 페이지로 이동한다.

e2e 테스트 예시

import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import * as request from 'supertest';
import { AppModule } from './../src/app.module';

describe('AuthController (e2e)', () => {
  let app: INestApplication;

  beforeAll(async () => {
    const moduleFixture: TestingModule = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();

    app = moduleFixture.createNestApplication();
    await app.init();
  });

  afterAll(async () => {
    await app.close();
  });

  it('등록되지 않은 사용자가, 로그인을 요청을 시도한다. 그러면 401 Unauthorized 상태 코드를 받아야 한다', async () => {
    // Given: 사용자가 등록되지 않은 상태
    const loginPayload = {
      email: 'nonexistent@example.com',
      password: 'invalidpassword',
    };

    // When: 사용자가 로그인 요청을 시도한다
    const response = await request(app.getHttpServer())
      .post('/auth/login')
      .send(loginPayload);

    // Then: 401 Unauthorized 상태 코드를 받아야 한다
    expect(response.status).toBe(401);
  });
});

 

 

+ Recent posts