개발 공부/Java

Java에서 List 를 테스트해보자

개발인생 2023. 7. 6. 18:21
반응형

테스트 코드를 작성하다보면 List 를 테스트할 상황이 많이 발생한다.

그 동안은 아무 생각없이 get을 사용해 테스트하는 방식을 주로 사용했다.

   @Test
   @DisplayName("List 테스트")
   void test20230629131424() {
      List<String> testList = Arrays.asList("test1", "test2", "test3");

      assertThat(testList.get(0)).isEqualTo("test1");
   }

개인적으로 위의 테스트 코드를 작성하며 여러가지 문제점을 겪었다.

  • get 을 사용해 직접 값을 꺼내오기 때문에 List 안의 다른 값들을 테스트하려면 코드의 중복이 발생한다.
  • 순서가 중요하지 않더라도 List 안의 값에 순서가 변경되면 테스트가 실패한다.
  • 0과 같은 매직넘버가 발생한다.

이로인해 코드의 가독성이 점점 떨어져가고 유지보수하기 어려운 코드가 되어가는 느낌을 받았다.

위의 코드는 list의 첫번 째 값이 무엇인지 테스트하는 코드이다.


AssertJ 에서 제공하는 다양한 api를 통해 List 를 효과적으로 테스트할 수 있다.

contain

컬렉션 안에 해당 값이 포함 되어 있는지를 검사하는 기능을 제공한다.

   @Test
   @DisplayName("List 테스트 - contain")
   void test20230629131425() {
      List<String> testList = Arrays.asList("test1", "test2", "test3");

      // test1이 포함되어 있나
      assertThat(testList).contains("test1");

      // 순서가 정확해야함
      assertThat(testList).containsExactly("test1", "test2", "test3");

      // 순서는 정확하지 않아도됨
      assertThat(testList).containsExactlyInAnyOrder("test1", "test3", "test2");
   }

객체를 가지고 있는 List 테스트하기

객체를 가지고 있는 List를 테스트해보자.

public class User {
      private final String name;
      private final String address;

      public User(String name, String address) {
         this.name = name;
         this.address = address;
      }

      public String getName() {
         return name;
      }

      public String getAddress() {
         return address;
      }
   }

간단한 유저 클래스를 선언한다.

객체안의 필드를 테스트하기 위해 extracting 메서드를 사용한다.

   @Test
   @DisplayName("List 테스트 - 객체")
   void test20230629131426() {
      List<User> testUsers = Arrays.asList(
            new User("test1", "인천"),
            new User("test2", "서울"),
            new User("test3", "강원도")
      );

      assertThat(testUsers)
            .extracting("address")
            .contains("인천", "서울", "강원도");

      assertThat(testUsers)
            .extracting("address")
            .containsExactlyInAnyOrder("인천", "강원도", "서울");

      assertThat(testUsers)
            .extracting(User::getAddress)
            .containsExactlyInAnyOrder("인천", "강원도", "서울");
   }

앞서 살펴본 contains 메서드와 함께 사용할 수 있다.

extracting 에서는 메서드 레퍼런스가 가능하다.


조금 더 복잡한 객체를 담은 List를 테스트해보자.


   public class User {
      private final String name;
      private final Address address;

      public User(String name, String address) {
         this.name = name;
         this.address = new Address(address);
      }

      public String getName() {
         return name;
      }

      public Address getAddress() {
         return address;
      }
   }

   public class Address {
      private final String city;

      public Address(String city) {
         this.city = city;
      }

      public String getCity() {
         return city;
      }
   }

테스트를 위한 클래스를 선언한다.

User 클래스가 Address 클래스를 포함하는 관계이다.

각각의 유저 인스턴스 안에 있는 주소를 테스트하는 코드를 작성하면 다음과 같다.

   @Test
   @DisplayName("List 테스트 - 복잡한 객체")
   void test20230629131427() {
      List<User> testUsers = Arrays.asList(
            new User("test1", "인천"),
            new User("test2", "서울"),
            new User("test3", "강원도")
      );

      assertThat(testUsers)
            .extracting("address")
            .extracting("city")
            .contains("인천", "서울", "강원도");

      assertThat(testUsers)
            .extracting(User::getAddress)
            .extracting(Address::getCity)
            .contains("인천", "서울", "강원도");

      assertThat(testUsers)
            .extracting("address.city")
            .contains("인천", "서울", "강원도");
   }

이렇게 List 를 테스트하는 코드들을 알아봤다.

List를 다룰 일이 많은데 위의 방법으로 좀 더 견고하게 테스트할 수 있을 것 같다.

더 좋은 방법이 있다면 댓글로 남겨주시길..ㅎ

반응형