AssertJ 자주 사용하는 것들

테스트 케이스 작성할때, 많이 사용하는 AssertJ에 대해서 알아보자.

자세한 사용법, 예제는 AssertJ Guide 문서 를 확인하자!

1. Iteration

1.1. 컬렉션안에 값이 포함(contain)되어 있는지

List<String> list = List.of("1", "1", "2", "3");

// 포함되어 있니
assertThat(list).contains("1", "2");
// 중복된 값도 반영됨
assertThat(list).containsOnly("2","1","3");
// 순서 까지 정확해야함
assertThat(list).containsExactly("1", "1", "2", "3");
// 순서 정확하지 않아도됨
assertThat(list).containsExactlyInAnyOrder("2", "3", "1", "1");
assertThat(list).contains("1").contains("1").containsSequence("2", "3");
// 오직 한번만 있는 값들
assertThat(list).containsOnlyOnce("2", "3");
assertThat(list).containsAnyOf("2");

1.2. User객체, Dummy데이터 생성

간단한 User 객체를 만들고, dummy 데이터를 넣어준다.

@Data
public class User {
  private String name;
  private int age;
  private RoleType roleType;
  
  @Getter
  public enum RoleType {
      ADMIN, USER
  }
}

dummy 데이터를 생성

protected List<User> getUsers() {
  return List.of(betty(), andrew(), sam());
}

protected User sam() {
  return new User("sam", 25, RoleType.USER);
}

protected User betty() {
  return new User("betty", 20, RoleType.USER);
}

protected User andrew() {
  return new User("andrew", 32, RoleType.ADMIN);
}

1.3. 조건들을 만족하는지(satisfy)

List<User> users = getUsers();

// Consumer를 파라미터로 받는다.
// allSatisfy 모든 조건을 만족하는
assertThat(users).allSatisfy(user -> {
    assertThat(user.getName()).isNotEqualTo("mike");
    assertThat(user.getAge()).isGreaterThanOrEqualTo(20);
});

// 적어도 하나의 element 값을 충족시키는
assertThat(users).anySatisfy(user -> {
    assertThat(user.getName()).isEqualTo("andrew");
    assertThat(user.getAge()).isEqualTo(32);
});

// 어떤 조건도 만족하지 않는
assertThat(users).noneSatisfy(user -> {
    assertThat(user.getName()).isEqualTo("BTS");
});

1.4. Match 여부

// Predicate를 파라미터로 받는다.
assertThat(users).allMatch(user -> user.getName().length() > 0);
  • allMatch, anyMatch 를 메서드 체이닝 형태로 이어 나갈 수 있다.

1.5. Element 탐색

List<User> users = getUsers();

// element의 방향을 탐색하는것
// 객체 간의 비교를 할때는 EqualsAndHashCode를 선언해줘야 한다.
assertThat(users).first().isEqualTo(betty());
assertThat(users).element(1).isEqualTo(andrew());
assertThat(users).last().isEqualTo(sam());

객체간의 비교는 Equals와 HashCode를 오버라이딩 해줘야 한다. 그렇지 않게 되면, 객체 동일성(참조값을 비교)하게 됨으로, 우리가 예상하는 같은 이름과 나이를 가진 객체간의 비교가 되지 않는다.

1.6. Filter 테스트

// Filtering - Predicate
assertThat(users).filteredOn(user -> user.getName().startsWith("and"))
    .containsOnly(andrew());

// Filtering - Property(fieldName, value)
assertThat(users).filteredOn("name", "andrew")
    .containsOnly(andrew());

assertThat(users).filteredOn("name", in("andrew", "sam"))
    .containsOnly(andrew(), sam());

assertThat(users).filteredOn("name", notIn("mike", "nu"))
    .containsOnly(andrew(), sam(), betty());

// Property 를 메서드 레퍼런스로 표현가능하지만, not, in, notIn 오퍼레이터는 사용불가함
assertThat(users)
    .filteredOn(User::getName, "andrew")
    .filteredOn(User::getAge, 32)
    .containsOnly(andrew());


// null value 값을 찾는다.
assertThat(users).filteredOnNull("name").isEmpty();
  • filteredOn()메서드는 인자로 받는 조건에 맞게 값을 Filtering 해준다. 그리고 값의 존재여부를 비교한다.

1.7. Extracting single value

List<User> users = getUsers();

// field or property
assertThat(users)
    .extracting("name")
    .contains("andrew", "betty", "sam");

// 람다 표현식 가능
assertThat(users)
    .extracting(User::getName)
    .contains("andrew", "betty", "sam");

// map으로 변환해서 가능
assertThat(users)
    .map(User::getName)
    .contains("andrew", "betty", "sam");

// 2번째 파라미터로 강력하게 타입을 지정해서 > 이렇게 할거면 람다표현식이 나은듯
assertThat(users)
    .extracting("name", String.class)
    .contains("andrew", "betty", "sam");
  • User객체 안에 name필드로만 값들을 비교하고 싶을때, extract 메서드를 통해서 해당 컬렉션에서 필드값만 추출해서 비교가 가능하다.
  • extracting()메서드의 파라미터로 필드명을 입력해도 되고, 메서드 레퍼런스로도 표현 가능하다.
  • map()으로 변환해서 포함되어있는지 확인도 가능하다.

1.8. Extracting multiple value

assertThat(users).extracting("name", "age")
  .contains(tuple("andrew", 32),
            tuple("betty", 20),
            tuple("sam", 25)
           );

assertThat(users).extracting(User::getName, User::getAge)
  .contains(tuple("andrew", 32),
            tuple("betty", 20),
            tuple("sam", 25)
           );
  • 이번에는 하나의 값이 아닌, multiple value값을 추출한다.
  • tuple()메서드를 통해서 객체를 생성해준다. 당연히 extracting() 으로 넘긴 파라미터 필드 순서에 맞춰야 한다.

2. 정리

  • 오늘은 테스트케이스를 작성할때 왕왕쓰이는 AssertJ의 Iteration 섹션을 알아봤다.
  • 대충 이런게 있지 않을까 ? 찾아보면 웬만한건 있는듯 하다.

3. 참고

  • https://assertj.github.io/doc/#assertj-core-group-contains