Jest 기본 2 비동기(콜백, Promise, async await)

heisje·2023년 8월 3일
0
post-thumbnail

이전글

https://velog.io/@heisje/Jest-기본-1

코딩앙마님의 Jest강의를 중심으로 정리했습니다.
링크 : https://www.youtube.com/watch?v=snFRUjYR6j4

비동기 함수 테스트

비동기 함수 3가지
콜백, promise, async await를 테스트 하기위해 setTimeout을 사용해 비동기적으로 데이터를 반환하고 테스트 해보자.

콜백

콜백 패턴을 가지고 있는 비동기 함수의 테스트 코드를 작성하는 법을 알아보자

테스트 대상 함수 작성

getName: (callback) => {
    // 콜백 함수를 3초뒤에 실행시키는 함수
    const name = "Mike";
    setTimeout(() => {
      callback(name);
    }, 3000);
  },

테스트 코드 작성
기존 테스트 코드와 다른 점은 done을 작성해줘야 테스트가 정상적으로 종료되는 것이다.

test("3초 후에 받아온 이름은 Mike done", done => {
  function callback2(name){
    expect(name).toBe("Mike");
    done();            
  }
  fn.getName(callback2);  
})

테스트 코드 try catch

test("3초 후에 받아온 이름은 Mike done", (done) => {
  function callback(name) {
    try {
      expect(name).toBe("Mike");
      done();
    } catch (error) {
      done();
    }
  }
  fn.getNameErr(callback);
});

콜백 패턴 주의사항

test("3초 후에 받아온 이름은 Tom", () => {  
  function callback1(name){
    expect(name).toBe("Tom");
  }
  fn.getName(callback1);   // jest는 실행이 끝에 도달하게되면 테스트가 끝나게 된다. 그래서 비동기 호출을 기다리지 않고 종료되었다.
})

결과코드
아래와 같이 1ms만에 성공으로 통과된다. 왜냐하면 jest는 실행이 끝에 도달하게되면 테스트가 끝나게 된다. 그래서 비동기 호출을 기다리지 않고 종료되었다.
그리하야 done을 써줘야 된다.

 PASS  ./fn.test.js
  ✓ 3초 후에 받아온 이름은 Mike done (3006 ms)
  ✓ 3초 후에 받아온 이름은 Tom (1 ms)

...
Ran all test suites.
Jest did not exit one second after the test run has completed.

'This usually means that there are asynchronous operations that weren't stopped in your tests. Consider running Jest with `--detectOpenHandles` to troubleshoot this issue.
/Users/home/Documents/sw/jest/node_modules/expect/build/index.js:314
      throw error;
      ^

JestAssertionError: expect(received).toBe(expected) // Object.is equality

Expected: "Tom"
Received: "Mike"
    ...

Node.js v20.5.0

Promise

프로미스 패턴은 프로미스 객체를 주고 받기 때문에 실용성이 좋다.
테스트 대상 함수

const fn = {
  // 프로미스 객체를 성공으로 반환시키는 경우
  getNamePromise: () => {
    const name = "Mike";
    return new Promise((res, rej) => {
      setTimeout(() => {
        res(name);
      }, 3000);
    });
  },

  // 실패로 반환시키는 경우
  getNamePromiseRejects: () => {
    return new Promise((res, rej) => {
      setTimeout(() => {
        rej("서버에러...");
      }, 3000);
    });
  },
};
module.exports = fn;

테스트 코드
return으로 프로미스를 반환해줘야한다. resolvesrejects matcher를 사용해 promise객체 결과값을 기다릴 수 있다.

const fn = require("./fn");

test("3초 후에 받아온 이름은 Mike Promise", () => {
  return fn.getNamePromise().then((age) => {
    expect(age).toBe("Mike");
  });
});

test("matcher를 사용하여 성공을 나타내는 방법", () => {
  return expect(fn.getNamePromise()).resolves.toMatch("Mike");
});

test("matcher를 사용하여 실패를 나타내는 방법", () => {
  return expect(fn.getNamePromiseRejects()).rejects.toMatch("서버에러...");
});

async await

가장 자주 사용하는 비동기 패턴인 만큼 잘 알아두자!
async await로 done이나 matcher를 쓰지않고 비동기 함수를 기다릴 수 있다.
테스트 코드

// matcher를 쓰지 않는 방법
test("async await를 사용하여 간단하게 나타내는 방법", async () => {
  const name = await fn.getNamePromise();
  expect(name).toMatch("Mike");
});

// matcher를 쓰는 방법
test("resolves를 사용하여 나타내는 방법", async () => {
  await expect(fn.getNamePromise()).resolves.toMatch("Mike");
});
profile
김희제의 기술블로그

1개의 댓글

comment-user-thumbnail
2023년 8월 3일

유익한 글이었습니다.

답글 달기