본문 바로가기

[Project] 프로젝트 삽질기67 (feat DOO 단위 테스트)

어가며 

이 글에서 비즈니스 로직과 이벤트 전달 로직을 분리하는 과정을 공유했습니다. 이번 글에서는 테스트 코드를 활용해서 이벤트를 전달하는 코드가 호출되었는지, 그리고 이벤트를 전달하는 코드를 호출하기 위해 어떤 객체가 전달되었는지 확인한 방법을 공유하고자 합니다. 그 과정에서 테스트 코드를 어떻게 작성했는지 함께 공유하겠습니다.

 

 

 

 


 

 

 

 

테스트 코드 작성 준비

기존 코드는 아래와 같이 구성되어 있었습니다. 만약 아래 코드로 단위 테스트를 작성한다면, 테스트 코드를 작성하기 어렵습니다. hackle, amplitude SDK를 직접 제어하기 어렵고, sdk를 활용해서 외부에 데이터를 전달하는 것이기 때문에 테스트를 하기 위해서는 외부의 환경에 의존해야 합니다. 

 

 

 

 

 

문제를 해결하기 위해선, 직접 제어하기 어려운 hackle, amplitude에 이벤트를 전달하는 코드를 외부에서 주입받아서 활용한다면 동일한 인터페이스에 맞춘 테스트 더블을 주입함으로써 코드를 제어할 수 있고, 외부의 환경에 의존하는 코드를 개선할 수 있다고 판단했습니다. 

 

 

 

 

 

 

위와 같이 코드를 개선한 후, createUser 메서드를 테스트하는 코드를 작성했습니다. 테스트 코드를 작성할 때 trackerService의 sendEvent 메서드가 잘 호출되었는지 확인하고 싶었고, trackerService.sendEvent 메서드가 호출될 때 EnumClass에서 객체가 잘 생성되어서 전달되었는지도 확인하고 싶었습니다. 그럼 테스트 코드를 어떻게 작성했는지 함께 살펴보겠습니다. 

 

 

 

 

 

 


 

 

 

 

 

 

테스트 코드 작성

NestJS를 활용하면서, Jest를 활용해서 테스트 코드를 작성하고 있습니다. 검증의 대상이 sendEvent의 메서드가 호출되었는지, 그리고 호출될 때 매개변수로 EnumClass가 제대로 전달됐는지를 확인하고 싶었습니다. 검증하기 위해서 먼저 Jest에서 제공하는 spyOn을 사용하려 했습니다. spyOn을 활용한다면 메서드의 호출 여부와 어떻게 호출되었는지 확인할 수 있다고 판단했습니다. spyOn을 활용하여 아래와 같이 테스트 코드를 작성했습니다. 

 

 

 

 

 

 

위와 같이 작성함으로써 sendEvent 메서드가 호출하는지, 호출했을 때 매개변수로 어떤 값이 전달되는지 등을 확인할 수 있었습니다. 하지만 spyOn이라는 메서드를 어떻게 활용해야 하는지 모른다면 코드를 이해하기 쉽지 않겠다는 생각이 들었습니다. 그리고 현재는 Jest를 사용하고 있는데, 만약 다른 테스트 러너를 사용한다면 테스트 코드 전체를 수정해야 하는 번거로움이 생기겠다고 생각했습니다.

 

 

 

다른 언어로 성장하기

썸네일 이미지는 데브경수님의 인스타툰에서 가져왔습니다. 작년 4월까지 JVM 언어 / Spring 을 사용하면서 커리어를 쌓다가, 최근 이직을 하면서 Node.js (JS / TS) 에서 개발경험을 쌓고 있다. 처음 Nod

jojoldu.tistory.com

 

 

추가로, 위 글을 보면서 Jest의 Mock을 활용하면 테스트하기 어려웠어야 할 의존성 디자인 안에서도 테스트하기 너무 쉽다는 문제도 있다는 것을 배웠습니다. Jest에서 제공하는 spyOn과 mock이 아닌, 다른 방법으로 mocking을 하는 방법을 알고 싶었습니다. 

 

 

 

jest.mock 보다 ts-mockito 사용하기 (feat. Node.js)

NodeJS 기반의 백엔드에서는 NestJS, RoutingControllers 등 최근 대세가 되는 MVC 프레임워크들이 모두 Class를 기반으로 한 DI (Dependency Injection) 방식을 사용하고 있다. 그러다보니 Jest의 Mocking 방식은 백엔

jojoldu.tistory.com

 

 

문제를 해결하기 위해 위 링크를 참고하면서, ts-mockito 라이브러리를 활용한다면 mocking을 보다 효율적으로 처리할 수 있다고 생각했습니다. 

 

 

 

 

 

 

 

ts-mockito를 활용하면 Jest의 spyOn와 mock보다 직관적으로 사용할 수 있다는 장점이 있었습니다. 위에서 활용한 spyOn을 보면 코드를 구축하려면 긴 코드를 작성해야 했습니다. 그런데 ts-mockito에서 제공하는 when, mock, verify 등의 메서드를 활용하면 직관적으로 테스트 환경을 구축할 수 있었습니다. 추가적으로 테스트 러너를 변경하더라도, mocking을 처리하는 코드는 변경하지 않아도 되는 큰 장점이 있었습니다. 

 

 

 

 

 

 

 

이를 위해 위처럼 ts-mockito를 활용해서 테스트 코드를 작성했습니다. 

 

 

 

 

 

when 메서드를 활용해서 특정 상황에서 어떤 반환값 혹은 행위를 할지 지정할 수 있습니다. 유저의 정보를 저장하는 로직이 UserApiService 클래스에 존재하기 때문에, thenResolve 메서드를 통해 트랜잭션의 처리 결과 특정 객체를 전달해야 한다고 구성할 수 있었습니다.

 

 

 

 

 

 

그리고 verify 메서드를 활용해서 지정된 인자가 특정 조건에 맞춰 몇 번째 순서로 호출되었음을 검증할 수 있었습니다. verify 메서드를 통해 trackerService의 sendEvent 메서드가 몇 번 호출됐는지도 검증할 수 있었습니다. 마지막으로 capture 메서드를 통해 메서드의 인자를 확인합니다. capture 메서드를 통해 trackerService의 sendEvet 메서드가 의도한 대로 호출되었는지를 검증할 수 있었습니다. sendEvent 메서드에 TrackerEventEnum 클래스를 생성해서 전달하기 때문에, 객체가 제대로 전달됐는지를 확인할 수 있었습니다. 

 

위의 과정을 거쳐서 이벤트 전달 로직을 테스트할 수 있었습니다. 단위 테스트를 작성하면서 모킹을 활용해서 테스트를 작성했을 때 장점만 존재하는 것은 아니었습니다. 모킹을 활용해서 단위 테스트를 작성함으로써, UserApiService의 코드에 의존적인 코드를 작성할 수밖에 없었습니다. UserApiService에서는 transaction 메서드를 호출했을 때의 결과로 특정 객체를 전달해야 한다는 내부 구현 상황을 테스트 코드에서도 드러내야 했습니다. 만약 UserApiService 클래스의 코드가 변경된다면 테스트 코드도 변경될 수 있는, 낮은 리팩터링 내성 문제가 발생할 수 있었습니다. 그리고 테스트 코드를 작성하는 비용 또한 추가될 수 있다는 단점이 있었습니다. 그럼에도 UserApiService 클래스의 코드를 전부 수정하기보다는 조금씩 코드를 추가하거나 수정하는 경우가 더 많을 것이라고 생각하고 있기 때문에, 이벤트를 전달하는 코드가 정상적으로 전달되는지 테스트 코드를 통해 확인하는 것이 더 낫다고 판단하여 모킹을 활용해서 테스트 코드를 작성했습니다. 

 

 

 

 

 

 

 

 


 

 

 

 

 

 

 

 



 

마치며

글을 읽어주셔서 감사합니다. 저도 완벽하게 혹시나 코드에서 개선이 필요한 부분이 있다면 피드백을 반영해서 수정하겠습니다.

 

 

 

 

 

 

 


 

 

 

 

 

출처

 

Jest의 jest.fn(), jest.spyOn()를 이용한 함수 모킹

Engineering Blog by Dale Seo

www.daleseo.com

 

효율적인 테스트를 위한 Stub 객체 활용법

구현에 의존하지 않은 테스트 코드 작성을 위해 Stub 객체를 효율적으로 활용하는 방법에 대해 소개합니다.

medium.com

 

jest.mock 보다 ts-mockito 사용하기 (feat. Node.js)

NodeJS 기반의 백엔드에서는 NestJS, RoutingControllers 등 최근 대세가 되는 MVC 프레임워크들이 모두 Class를 기반으로 한 DI (Dependency Injection) 방식을 사용하고 있다. 그러다보니 Jest의 Mocking 방식은 백엔

jojoldu.tistory.com

 

다른 언어로 성장하기

썸네일 이미지는 데브경수님의 인스타툰에서 가져왔습니다. 작년 4월까지 JVM 언어 / Spring 을 사용하면서 커리어를 쌓다가, 최근 이직을 하면서 Node.js (JS / TS) 에서 개발경험을 쌓고 있다. 처음 Nod

jojoldu.tistory.com