테스트에는 크게 시스템 테스트, 통합 테스트, 단위 테스트가 있습니다. 각 테스트마다 테스트하려는 관점이 다르므로, 이에 따라 적절한 테스트 방법을 선택해야 합니다.

  • 단위 테스트는 하나의 클래스를 인스턴스화하고 해당 클래스의 인터페이스를 통해 기능을 테스트하는 것을 말합니다. 만약 해당 클래스가 의존하고 있는 다른 클래스가 있다면 목(mock)으로 대체합니다.
  • 통합 테스트는 두 계층 간에 걸쳐서 네트워크가 잘 작동하는지 검증하는 테스트입니다.
  • 시스템 테스트는 특정 유스케이스가 전 계층에서 잘 작동하는지 검증하기 위한 테스트입니다.

그렇다면 헥사고날 아키텍처에서 각 계층은 어떤 테스트를 작성하는 게 좋을지 살펴보도록 하겠습니다.

도메인 엔티티 테스트하기

도메인 엔티티에서는 비즈니스 규칙을 검증하는 테스트가 필요합니다. 도메인 엔티티는 다른 클래스에 거의 의존하지 않기 때문에 단위 테스트로 충분히 테스트가 가능합니다.

유스케이스 테스트하기

유스케이스에서도 비즈니스 규칙을 검증하는데, 주로 도메인 객체 간의 상호작용을 테스트합니다. 유스케이스가 의존하고 있는 다른 서비스들은 Mocking 하여 처리할 수 있으므로 단위 테스트로 테스트가 가능합니다.

사실 의존성의 상호작용을 테스트하고 있기 때문에 통합 테스트에 가깝습니다.

웹 어댑터 테스트하기

웹 어댑터에서는 HTTP를 통한 입력, 입력에 대한 유효성, 유스케이스로 사용할 수 있는 포맷으로 매핑 그리고 유스케이스에 잘 전달하고 있는지를 검증하는 테스트가 필요합니다. 만약 단위 테스트로 테스트하면 각 단계에 대한 커버리지가 낮아지고, 프레임워크 구성 요소들이 프로덕션 환경에서 정상적으로 작동하는지 확신할 수 없기 때문에 통합 테스트가 적합합니다.

영속성 어댑터 테스트하기

영속성 테스트는 입력을 데이터베이스에 올바르게 매핑하고, 결과를 잘 반환하는지 검증해야 합니다. 그래서 통합 테스트를 작성해야 합니다.

스프링에서는 테스트에서는 기본적으로 in-memory 데이터베이스를 사용합니다. 그래서 쉽게 테스트할 수 있다는 장점이 있습니다. 하지만 프로덕션 환경에서는 in-memory 데이터베이스를 사용하지 않기 때문에, 테스트에는 통과하지만 실제로는 동작하지 않는 경우가 생깁니다. 따라서 통합 테스트를 작성할 때는 실제 데이터베이스를 이용해서 테스트를 하는 것을 권장합니다.

시스템 테스트로 주요 경로 테스트하기

시스템 테스트는 사용자 관점에서 애플리케이션을 검증할 수 있습니다. 각 계층에서 테스트한 단위 테스트와 통합 테스트와 겹친다고 생각할 수도 있습니다. 하지만 시스템 테스트는 단위 테스트나 통합 테스트에서 발견할 수 없는 또 다른 종류의 버그를 발견할 수 있습니다. 예를 들어 계층 간 매핑 같은 것들을 검증할 수 있습니다.

또한 시스템 테스트는 여러 개의 유스케이스를 결합해서 시나리오를 만들 때 더 빛이 납니다. 각 시나리오는 사용자가 애플리케이션을 사용하면서 거쳐갈 특정 경로를 의미합니다. 시스템 테스트를 통해 중요한 시나리오들이 커버된다면 최신 변경사항들이 애플리케이션을 망가뜨리지 않았음을 가정할 수 있고, 배포될 준비가 됐다는 확신을 가질 수 있습니다.

테스트 시 Mocking이 버거워지거나 어떤 종류의 테스트를 써야 할지 모르겠다면, 아키텍처에 문제가 있다는 신호입니다. 육각형 아키텍처에서 입출력 포트는 아주 뚜렷한 Mocking 지점이 되어, 이러한 문제를 빠르게 발견할 수 있습니다.