@Nested를 활용하여 계층 구조의 테스트 코드 작성하기

junhyeong·2024년 2월 18일
8

같이 공부를 하던 분의 프로젝트 코드를 살펴봤는데 테스트 코드에서 @Nested이라는 Annotation을 사용하시는 것을 발견했습니다.

그래서 @Nested에 대해 공부를 해본 결과 저의 프로젝트에도 적용해 보면 좋겠다는 생각이 들었고, 어떻게 활용했는지 글을 작성해 보려고 합니다.

@Nested

@Nested는 JUnit 5에서 도입된 기능으로, 테스트 클래스 내에서 논리적으로 관련된 테스트 메서드를 그룹화하는 데 사용됩니다. 이를 통해 테스트 클래스를 더욱 구조화하고 가독성을 높일 수 있습니다.

기존의 코드

기존에 작성한 코드를 살펴보고 @Nested를 통해 계층을 나눠보겠습니다

class GetEmployeeDetailServiceTest {
	// 생략
	
	@Test
    @DisplayName("직원 상세 정보 조회")
    void employeeDetail() {}
    
    @Test
    @DisplayName("직원이 존재하지 않는 경우")
    void employeeDetailFailedWithEmployeeNotFoundException() {}
     
    @Test
    @DisplayName("부서가 존재하지 않는 경우")
    void employeeDetailFailedWithDepartmentNotFoundException() {}
     
    @Test
    @DisplayName("직무가 존재하지 않는 경우")
    void employeeDetailFailedWithJobNotFoundException() {}
}

저는 테스트 코드를 작성할 때, 먼저 어떤 메서드인지 작성하고 각 실패 케이스를 나타내기 위해 FailedWith..같은 형식으로 테스트를 작성하고 있습니다.

제가 작성하는 방식일 뿐이니 참고만 해주시면 좋을 것 같습니다.

작성할 때 성공 케이스는 위쪽, 실패 케이스는 아래쪽에 두는 편입니다. 사실 지금 이대로도 작성자인 저의 입장에서는 크게 문제가 없어 보입니다.

하지만 처음보는 사람 입장에서는 이해하기 어려울 수 있고, 계층을 나눠서 구분해 주면 가독성이 더 좋아질 거라는 생각이 들어 아래처럼 코드를 변경해 보았습니다.

수정결과

class GetEmployeeDetailServiceTest {
	// 생략
    
    @DisplayName("성공")
    @Nested
    class Success {
	
      @Test
      @DisplayName("직원 상세 정보 조회")
      void employeeDetail() {}
    }
    
    @DisplayName("실패")
    @Nested
    class Failure {
    
      @Test
      @DisplayName("직원이 존재하지 않는 경우")
      void employeeDetailFailedWithEmployeeNotFoundException() {}

      @Test
      @DisplayName("부서가 존재하지 않는 경우")
      void employeeDetailFailedWithDepartmentNotFoundException() {}

      @Test
      @DisplayName("직무가 존재하지 않는 경우")
      void employeeDetailFailedWithJobNotFoundException() {}
    }
}

@Nested를 사용하여 관련된 테스트 메서드를 실패, 성공으로 그룹화하여 가독성을 향상시켰습니다.

테스트 코드와 결과 창에서 실패 케이스와 성공 케이스를 구분하기 쉬워진 것을 볼 수 있습니다.

또 다른 활용법

저는 비즈니스 로직이 있는 Service 클래스를 각 기능마다 나눠서 관리하고 있습니다. (GetEmployeeService, CreateEmployeeService 등)

그래서 위에 코드처럼 성공, 실패로만 나눠도 충분했습니다. 하지만 EmployeeService처럼 전체 기능을 관리하는 Service나 여러 기능이 있는 경우에는 관심사에 따라 계층을 분리하는 것이 더 좋은 방법일 수 있습니다.

이외에도 다른 분들이 작성한 코드를 살펴봤습니다. 링크를 보면 기계인간님은 Describe, Context, It 방식으로 계층을 나눈 걸 확인 할 수 있었습니다.

  • Describe: 테스트 대상을 명사로 작성
  • Context: ~인 경우, ~할 때, 만약 ~ 하다면 과 같이 상황 또는 조건 기술
  • It: 위에서 명사로 작성한 테스트 대상의 행동 작성
    • 테스트 대상의 행동은 ~이다, ~한다, ~를 갖는다가 적절함
    • ~된다 같은 수동형 표현은 좋지 않음

이 방식으로 저의 코드를 변경한다면 아래처럼 바꿀 수 있을 것입니다.

이처럼 @Nested를 활용하여 테스트 클래스 내에서 여러 하위 컨텍스트를 만들 수 있으며, 용도에 맞게 다양한 방식으로 활용할 수 있습니다.

마치며

평소에 다른 분들의 Repository를 보며 코드를 많이 참고하는 편입니다. 그러다 보면 생각지도 못하게 제가 고민했던 부분을 해결할 수 있거나 좋은 코드 작성법을 많이 알 수 있기 때문입니다.

저는 사실 별다른 문제를 느끼지 못했기 때문에, 만약 다른 분의 코드를 보지 않았다면 계속해서 이전과 같은 코드를 작성했을 것입니다.

이처럼 다른 분들의 코드를 살펴보고 내 코드에 적용해 보면 더 좋은 방법을 발견할 수 있습니다. 앞으로도 더 좋은 코드를 위해 더 많은 분들의 코드를 참고하고, 공부해 볼 생각입니다.

참고

profile
매일매일이 성장하는 하루가 될 수 있도록!

0개의 댓글