과정을 즐기자

제어할 수 없는 영역을 테스트 하는 방법 본문

테스트 코드

제어할 수 없는 영역을 테스트 하는 방법

320Hwany 2024. 6. 30. 16:22

이번 글에서는 시간, 랜덤 값과 같은 제어할 수 없는 영역을 테스트하는 방법에 대해 작성해보겠습니다.

예시로 날짜에 따라 할인을 적용하는 간단한 로직을 만들어보았습니다.

 

Bad - 의존성이 내부에 숨겨져 있음

위 코드는 2024년 6월 30일 이전 날짜인 경우에만 2000원의 할인이 적용됩니다.

잘 작성한 것 같아보이지만 문제점이 보이시나요?

 

Bad - 테스트하기 어려움

 

할인 날짜보다 이전/이후 날짜에 따라 할인 적용 여부가 결정되는데 시간의 흐름에 따라 테스트 코드가 달라질 수 있습니다.

제어할 수 없는 영역인 시간에 대한 정보가 메소드 내부에 숨겨져 있기 때문입니다.

즉, 해당 코드는 테스트 코드를 작성하기가 어렵습니다.

 

📕 제어할 수 없는 영역은 밖으로 밀어내자

이제 이 메소드를 리팩토링하여 테스트할 수 있도록 수정해 보겠습니다.

첫 번째로 테스트할 수 없는 영역에 대한 값을 밖으로 밀어내는 방법이 있습니다. 

즉, 파라미터로 주입을 받도록 수정하는 방식입니다.

Better - 파라미터로 주입

현재 시간과 할인 적용 날짜를 모두 파라미터로 주입받도록 수정하였습니다.

Better - 도메인 영역 테스트 가능

이렇게 수정하니 아까는 테스트할 수 없었던 2가지 테스트 모두 테스트 가능해졌습니다.

📕 가능하면 계속 밖으로 밀어내야 하나?

Order 도메인 영역에 대해서는 테스트할 수 있었지만 Order를 사용하는 OrderService의 메소드 안에서

현재 시간을 생성하기 때문에 여전히 이 부분에 대한 테스트는 작성할 수 없습니다.

Bad - 서비스 영역 테스트하기 어려움

이 부분도 파라미터로 받는 방식으로 수정해보겠습니다.

Better - 서비스 영역 테스트 가능

 

마찬가지의 방식으로 OrderService 영역도 제어할 수 없는 영역인 시간을 파라미터로 주입 받아 테스트 가능하도록 

수정하였습니다. 그렇다면 어디까지 밖으로 밀어내야 하는 것일까요?

가능하면 많은 영역을 테스트 할 수 있도록 Controller에서 전달 받는 곳까지 밀어내는 것이 좋은 방법이라고 생각합니다. 

📕 결국은 의존성을 드러내는 것

제어할 수 없는 영역을 파라미터로 주입 받는 다는 것은 결국에는 숨겨져 있는 의존성을 드러낸다는 말입니다.

이것을 생각해보면 다른 방법으로도 테스트 할 수 있습니다.

 

하나의 메소드에서 제어할 수 없는 영역이 많아지고 다른 파라미터들도 많아진다면 파라미터 개수가 4, 5개 이상이 되어

가독성이 떨어질 수 있습니다. 이때 의존성을 드러낸다는 것을 생각하고 생성자 주입을 통해 개선해보겠습니다.

 

DateCreator 인터페이스, 이를 구현한 DateProvider (운영), FakeDateProvider (테스트용)을 구현해보겠습니다.

먼저 현재 시간을 반환하기 위한 인터페이스 DateCreator를 구현합니다. 

Better - 의존성을 드러내기 위한 인터페이스와 구현체

운영 코드에서 사용할 DateProvider를 구현하고 LocalDate.now()로 현재 시간을 반환합니다.

테스트 코드에서 사용할 FakeDateProvider를 구현하고 시간을 제어하기 위해 생성자를 통해 시간을 주입 받도록 합니다.

 

이제 OrderService를 DateCreator를 사용하도록 수정해보겠습니다.

 

비즈니스 코드에서 파라미터로 주입 받지 않고 DateCreator를 생성자로 주입받아서 운영/테스트에 따라

DateCreator의 동작 방식을 변경하는 방식으로 수정하였습니다.

그림으로 다시 한 번 살펴보겠습니다.

 

운영 환경 

테스트 환경

생성자 주입을 통해 DI를 적용하였습니다. OrderService는 DateCreator 인터페이스에 의존하여 런타임 시점에

DateProvider, FakeDateProvider 구현체를 사용합니다. 즉, 상위 모듈과 하위 모듈이 모두 추상화에 의존하는

의존성 역전이 적용된 사례라고 볼 수 있을 것 같습니다.

 

📕 정리

제어할 수 없는 영역을 테스트하기 위한 핵심은 내부에 숨겨져 있는 의존성을 밖으로 드러내야 합니다.

의존성을 드러내기 위해 파라미터로 주입 받는 방식, 새로운 인터페이스를 정의하여 생성자로 주입하는 방식이 있습니다.

간단한 코드에서는 파라미터로 주입 받는 방식이 좋을 것 같고 서비스가 커짐에 따라서는 생성자로 주입하는 방식도

고려해볼 수 있을 것 같습니다.