AssertJ란?

JUnit으로 테스트 코드 작성시 JUnit에서 제공하는 Assertion 에는 가독성에 한계가 있다. 이를 해결하기 위해 AssertJ 라이브러리를 통해 좀 더 직관적인 테스트 코드를 작성할 수 있도록한다. 아래는 두 값이 같은지 확인하는 JUnit Assertion과 AssertJ를 활용했을 때의 비교이다.

assertEquals("test context", "a", "a"); // JUnit
assertThat("a").as("test context").isEqualTo("a"); // AssertJ

사용해보기

AssertJ를 활용한 코드는 대부분 아래와 같은 형식으로 작성할 수 있다.

assertThat(objectUnderTest).method1().method2().

잘못된 사용 예시

  • assertion 호출을 잊지마라. assertThat만으로는 어떤 assertion도 만들 수 없다. assertThat만 사용할 경우 절대 fail이 발생하지 않는다.

예시:

// DON'T DO THIS ! It does not assert anything and passes
assertThat(1 == 2);
// DO THIS: (fails as expected)
assertThat(1).isEqualTo(2);
  • assertion 이후에 as()를 호출하지마라. assertion 이후의 as는 작동하지 않을 수 있다.

예시:

// DON'T DO THIS ! as/describedAs have no effect after the assertion
assertThat(actual).isEqualTo(expected).as("description");
assertThat(actual).isEqualTo(expected).describedAs("description");
// DO THIS: use as/describedAs before the assertion
assertThat(actual).as("description").isEqualTo(expected);
assertThat(actual).describedAs("description").isEqualTo(expected);
  • assertion 이후에 FailMessage 및 overridingErrorMessage를 호출하지마라. 작동하지 않을 수 있다.
// DON'T DO THIS ! overridingErrorMessage/withFailMessage have no effect after the assertion
assertThat(actual).isEqualTo(expected).overridingErrorMessage("custom error message");
assertThat(actual).isEqualTo(expected).withFailMessage("custom error message");
// DO THIS: use overridingErrorMessage/withFailMessage before the assertion
assertThat(actual).overridingErrorMessage("custom error message").isEqualTo(expected);
assertThat(actual).withFailMessage("custom error message").isEqualTo(expected);
  • comparator를 assertion 이전에 호출하라.

예시:

// DON'T DO THIS ! Comparator is not used
assertThat(actual).isEqualTo(expected).usingComparator(new CustomComparator());
// DO THIS:
assertThat(actual).usingComparator(new CustomComparator()).isEqualTo("a");

주요 메소드

  • isEqualTo: 실제 값과 주어진 값이 같은지 확인한다.
public SELF isEqualTo(Object expected)

예시:

 // assertions succeed
 assertThat("abc").isEqualTo("abc");
 assertThat(new HashMap<String, Integer>()).isEqualTo(new HashMap<String, Integer>());

 // assertions fail
 assertThat("abc").isEqualTo("123");
 assertThat(new ArrayList<String>()).isEqualTo(1);
  • as: 이후에 호출된 assertion의 설명을 설정한다.
public SELF as(String description, Object... args)
try {
   // set an incorrect age to Mr Frodo which is really 33 years old.
   frodo.setAge(50);
   // specify a test description (call as() before the assertion !), it supports String format syntax.
   assertThat(frodo.getAge()).as("check %s's age", frodo.getName()).isEqualTo(33);
 } catch (AssertionError e) {
   assertThat(e).hasMessage("[check Frodo's age]\n
                             expected: 33\n
                             but was : 50");
 }
  • contains: 실제 그룹에 주어진 값이 포함되어 있는지 확인한다.
public SELF contains(ELEMENT... values)

예시:

 Iterable<String> abc = newArrayList("a", "b", "c");

 // assertions will pass
 assertThat(abc).contains("b", "a");
 assertThat(abc).contains("b", "a", "b");

 // assertion will fail
 assertThat(abc).contains("d");
  • containsExactly: 실제 그룹에 지정된 값이 포함되어 있는지 순서대로 확인한다.
public SELF containsExactly(ELEMENT ... values)

예시:

 // an Iterable is used in the example but it would also work with an array
 Iterable<Ring> elvesRings = newArrayList(vilya, nenya, narya);

 // assertion will pass
 assertThat(elvesRings).containsExactly(vilya, nenya, narya);

 // assertion will fail as actual and expected order differ
 assertThat(elvesRings).containsExactly(nenya, vilya, narya);
  • assertThatThrownBy: 코드에서 예외가 발생하는지 확인한다.
public static AbstractThrowableAssert<?,? extends Throwable> assertThatThrownBy(ThrowableAssert.ThrowingCallable shouldRaiseThrowable, String description, Object... args)

예시:

import static org.assertj.core.api.Assertions.*;

assertThatThrownBy(() -> {
    // 확인할 코드
}).isInstanceOf(IndexOutOfBoundsException.class) // IndexOutOfBoundsException이 발생한 경우
  .hasMessageContaining("Index: 2, Size: 2"); // Exception 메시지가 "Index: 2, Size: 2"인 경우
  • assertThatExceptionOfType: assertThatThrownBy 와 같은 목적이지만 가독성이 더 좋은 경우 이 메소드를 사용한다.
public static <T extends Throwable> ThrowableTypeAssert<T> assertThatExceptionOfType(Class<? extends T> exceptionType)

예시:

import static org.assertj.core.api.Assertions.assertThatExceptionOfType;

assertThatExceptionOfType(IndexOutOfBoundsException.class)
  .isThrownBy(() -> {
      // 확인할 코드
}).withMessageMatching("Index: \\d+, Size: \\d+");

자주 발생하는 Exception의 경우마다 별도의 메서드를 제공하고 있다.

  • assertThatIllegalArgumentException()
  • assertThatIllegalStateException()
  • assertThatIOException()
  • assertThatNullPointerException()
  • hasSize: 실제 그룹의 값의 개수가 주어진 값과 같은지 확인한다.
public SELF hasSize(int expected)

예시:

 // assertions will pass
 assertThat(new String[] { "a", "b" }).hasSize(2);
 assertThat(Arrays.asList(1, 2, 3)).hasSize(3);

 // assertions will fail
 assertThat(new ArrayList()).hasSize(1);
 assertThat(new int[] { 1, 2, 3 }).hasSize(2);

관련 사이트

https://assertj.github.io/doc/

댓글남기기