테스트하기 쉬운 리액트 페이지 만들기
리액트에서 컴포넌트 단위의 유닛 테스트가 아닌, 페이지 단위의 통합테스트는 어렵다.
내가 왜 어려웠는지, 그리고 해결법에 대한 주관적인 생각을 작성함.
페이지 단위의 통합 테스트가 어려웠던 이유 #
페이지에서 사이드이펙트를 일으키는 로직을 직접적으로 호출해서 그렇다.
쏙쏙 들어오는 함수형 코딩 책에서 좋은 개념을 봤는데 아래와 같음.
- 액션 - 사이드이펙트를 일으키는 코드. 실행 시점이나 횟수에 영향을 받는다.
- 계산 - 사이드이펙트를 일으키지 않는 순수 함수. 전달받은 인자에만 의존하며 같은 입력값에 대해 항상 같은 결과를 반환함.
- 데이터 - 이벤트에 대한 결과물. 실행할 필요가 없다.
액션은 다른 코드들을 액션으로 오염시킨다.
(액션을 포함한 함수는 그 함수 역시 액션이 됨)
액션은 실행 시점과 횟수에 영향을 받아 항상 동일한 결과를 보장하지 않으므로 테스트를 하기 어렵다.
테스트 하기 쉬운 코드를 만들기 위해선 액션을 격리시켜 최대한 많은 코드를 계산 코드로 유지해야 한다.
(좋은 함수 만들기 - 부작용과 거리두기 - 이 게시글에도 비슷한 이야기가 나온다)
내 페이지 컴포넌트가 테스트가 어려운 이유는 컴포넌트 내부에서 액션함수인 데이터 패칭을 직접적으로 호출하기 때문이었다.
액션을 포함하고 있기 때문에 페이지 컴포넌트 역시 액션이 되어 같은 인풋(props)이더라도 동일한 결과를 보장할 수 없다.
해결법 #
컨테이너 - 프레젠테이션 패턴을 쓰자.
리액트 훅스가 나오고 나선 자주 안쓰이는 패턴 같지만, 액션을 격리하기 위한 장소로 컨테이너 컴포넌트가 제일 적합한 것 같다.
코드를 분리하기 위해서는 훅으로 충분하지만 문제는 훅을 사용하기 위해 컴포넌트 내부에서 직접 호출해야 하는 점이 테스트를 어렵게 만든다.
컨테이너에서 훅스를 호출하고 결과물을 props로 내려줘서 페이지 컴포넌트는 완전히 계산 코드만 남겨두는 것이 페이지를 테스트하기 쉽다.
컨테이너 대신 내부 액션을 모킹해서 대체하는 방법은 좋지 않은 것 같다.
내부 구현이 바뀌면 테스트도 영향 받을 수 있다.
컴포넌트의 인풋인 props의 인터페이스가 변경되는게 아니면 테스트 코드는 컴포넌트 변경에 영향받지 않는게 좋은듯