이전 포스트의 내용을 통해 비동기 코드의 테스트를 위해서 findAllByRole
퀴리를 사용하는 방법을 알아보았다. findAllByRole
로 Async.js
가 리렌더링 되기를 기다려 결과적으로 listitem
에 접근할 수 있다.
이유는 무엇일까? Http 요청을 보내고 있기 때문이다.
해당 예제와 같은 경우에는 API로부터 data를 fetch
해오고 있었다.
하지만 테스트를 할 때에는 일반적으로 서버에 http 요청을 보내지 않는다.
이유는 아래와 같다.
많은 네트워크 트래픽을 일으킨다. 특히 테스트 내용에 여러 요청이 있고, 이러한 테스트 파일 또한 많이 존재한다면 서버 과부하의 위험이 생긴다.
fetch
를 하지 않더라도 일부 컴포넌트가 서버로 post
요청을 보낸다면, 테스트를 하는 과정에서 데이터베이스에 데이터가 삽입되며 서버의 내용이 변경될 수 있다.
자세히 들어가기 앞서 유념해야 할 것은, 내가 직접 작성하지 않은 코드는 테스트해서는 안된다는 것이다. 그러므로 브라우저 내장 api인 fetch()
는 테스트하지 않도록 한다.
그렇면 도대체 어떤 내용을 테스트 하는 것일까?
fetch()
자체의 역할, 즉 요청전송 성공 여부 대신 fetch()
값을 이용하여 이어지는 내용을 테스트 하도록 한다.
1번 방식을 따르려면 '진짜' 요청대신 '가짜' 요청을 보내야 한다.
이를 위해 fetch()
를 mock 함수로 대체한다. 친절한 Jest에는 이를 위한 built-in support가 있다.
Async.test.js
에서 window.fetch
를 jest.fn
로 덮어 쓰도록 한다.
jest
객체의 유틸리티 메소드 중 하나인 fn()
은 mock 함수를 만드는 역할을 한다.
이렇게 '진짜' 요청에 '가짜' 요청의 뚜껑을 씌웠다면 마무리까지 완벽하게 가짜로 만들어주도록 하자.
이 jest.fn()
으로 덮어씌워진 window.fetch
에 mockResolvedValueOnce
라는 특수 메소드를 붙여 호출해보자.
mockResolvedValueOnce
는 말 그대로 fetch
의 resolved된 값을 흉내낼 수 있게 해준다.
이를 이해하기 위해 Async.js
로 돌아가 코드를 다시 살펴보도록 하자.
fetch
가 호출된 뒤 then
블록에서 resolve된 값을 활용하고 있음을 확인할 수 있다. 또한 해당 값에 json을 호출하고 있다. 우리는 바로 이 내용을 흉내내어 설정해주어야 한다.
그러므로 mockResolvedValueOnce
부분에 promise에 의해 resolved된 객체 값을 넣어주도록 하자.
json()
은 새로운 promise를 반환하기 때문에 async를 붙여주도록 한다. 여기서 반환되는 값은 fetch()
를 통해 API에서 받아오는 data의 내용이게 될 것이다.
테스트가 성공하는 시물레이션을 돌리기 위해 json()
으로 반환 받는 값은 위처럼 최소 하나의 post를 갖는 배열이라고 설정해 준다.
이후 테스트를 돌려보면 PASS 결과를 확인할 수 있다.
이로써 가짜 요청을 통한 비동기 코드 테스트가 완료되었다.
이러한 과정을 통해 불필요한 요청으로 인한 서버 과부하를 방지하고, 네트워크 트래픽 양도 감소 시킬 수 있었다. 더 나아가 fetch()
의 결과 제어로 다양한 테스트 시나리오를 시험해 볼 수도 있겠다.