3 분 소요


동기

이번 우테코 2주차 미션부터 메서드를 테스트하는 요구사항이 추가됐다.
그래서 이번에 테스트에 대해서 공부하고 정리하고자 이 글을 작성하게 됐다.
테스트에는 크게 단위 테스트, 통합 테스트가 있는데 오늘은 단위 테스트가 무엇인지, 그리고 어떻게 사용하는지에 중점을 맞추겠다.

단위 테스트

단위 테스트는 응용 프로그램에서 테스트 가능한 가장 작은 소프트웨어를 실행하여 예상대로 동작하는지 확인하는 테스트이다.

가장 작은 단위의 테스트로 일반적으로 클래스 또는 메서드 수준으로 테스트를 진행한다. Java에서는 JUnit을 통해 테스트가 진행되며, 특히 TDD와 함께 할 때 강력함을 발휘한다.

그러면 바로 사용 방법에 대해서 알아보자.

사용되는 에노테이션

@Test

@Test를 붙이면 메서드를 테스트 메서드로 인식하게 되고, 단일 실행할 수 있게 설정된다.
아래 코드를 보자

img1

메소드를 단독으로 실행할 수 있게 왼쪽에 녹색 커서가 생긴것을 확인할 수 있다.

실행 결과

img1

위와 같이 단독으로 테스트 메서드가 실행된 것을 확인할 수 있다.

@DisplayName

@DisplayName는 테스트 결과에 뜨는 이름을 설정할 수 있게 해준다. 테스트 결과에 같이 출력하고 싶은 내용을 추가할 수 있게 해준다.
바로 예시를 보자

img1

이렇게 해주면 아래와 같이 결과와 함께 미시지를 출력할 수 있다.

img1

@Before~ 시리즈

BeforeAll

이름부터 참 직관적이다. 모든 테스트 실행되기 전에 실행되는 것이라고 생각하면 된다.
단 한번만 실행되면 반드시 static으로 선언해야 한다.
바로 예시를 보자

img1

img1

결과를 보면 알 수 있듯이 먼저 실행이 출력되고 test1, test2의 내용이 출력되는 것을 확인할 수 있다. 이 때 주의할 점은 test1, test2의 순서는 보장되지 않는다. 내부적으로 실행 순서가 있긴 하지만 이는 JUnit의 내부 구조에 따라 바뀔 수 있다.
만약 순서를 지정하고 싶다면 @TestMethodOrder, @Order를 사용해서 지정할 수 있다.
일반적으로 단위 테스트는 서로 의존적이지 않기 때문에 순서가 상관이 없다. 하지만 경우에 따라 순서가 필요한 경우가 있을 수 있기 때문에 알아만 두자!

@BeforeEach

@BeforeEach는 각각의 테스트 메서드가 실행되기 전에 실행되는 메서드다. @BeforeAll은 처음에 한 번 실행되지만 @BeforeEach는 각 테스트마다 실행되는 차이점이 있다.
마찬가지로 예시를 보자

img1

img1

결과를 보면 알 수 있듯이 먼저 실행이 test1, test2 실행 이전에 출력되는 것을 확인할 수 있다.

@After~ 시리즈

@AfterAll

모든 테스트 메서드가 실행되고 단 한번만 실행된다. @BeforeAll과 정 반대라고 생각하면 된다.
마찬가지로 static 메서드로 선언해야 한다.
예시를 보자

img1

img1

나중 실행이 모든 테스트 메서드가 실행되고 난 후 출력된 것을 확인할 수 있다.

@AfterEach

위에 설명한 @BeforeEach의 정 반대라고 생각하면 된다. 테스트 메서드가 끝날때마다 호출된다.
마찬가지로 예시를 보자

img1

img1

이제 실제로 단위 테스트에 사용되는 메서드들을 살펴보자.
일반적으로 단정(assert) 메서드를 많이 사용하는데 크게 junit, assertj 두 종류가 있다.
assertj가 등장하기 전까지는 junit을 주로 사용했지만 이제는 assertj를 많이 사용한다. 기능은 동일하지만 가독성이 더 좋기 때문이다.
assertj는 메서드 체인을 지원하기 때문에 가독성이 더 좋다.
때문에 오늘은 assertj에 대해서 정리하고자 한다.

assertj

Assertions.assertThat()

isEqualTo(), isNotEqualTo()

이 메서드는 assertThat(a).isEqualTo(b)와 같이 사용된다. 대상a 와 기댓값 b의 값이 같은지 확인하는 메서드이다.
isNotEqualTo()는 정확히 반대라고 생각하면 된다.
예시를 보자

img1

isEqualTo(), isNotEqualTo()는 값을 통해 검증하는 단정 메서드이다.

isSameAs(), isNotSameAs()

이 메서드는 assertThat(a).isSameAs(b) 와 같이 사용된다. 대상 a가 기댓값 b와 같은 대상인지 주소값을 통해 확인한다.
사용법은 사실 isEqualTo()와 완전히 동일하기 때문에 생략하겠다.

여기서 가장 중요한 부분은 isEqualTo()isSameAs()의 차이점을 명확하게 아는 것이다.

isEqualTo() VS isSameAs()

  • isEqualTo()

isEqualTo()는 단순히 값이 동일한지 확인한다. 객체가 비교 대상이 될 때는 Java의 equals() 메서드의 기능을 한다.

  • isSameAs()

isSameAs()는 단순 값이 아니라 참조값이 같은지를 비교한다.

아래 코드를 보고 어떤 결과가 나올지 생각해보면 더 잘 이해할 수 있을 것이다.

img1

case 1, 2, 3, 4의 결과를 생각해보자.

case1 의 경우는 에러가 발생할 것이다. memberA, memberB는 다른 객체를 가리키고 있기 때문이다.

case2 의 경우는 어떨까? 마찬가지로 에러가 발생할 것이다. 이름도 같고 id도 같은데 왜 에러가 발생할까? 그 이유는앞에서 말한 것처럼 isEqualTo()는 Java문법의 equals()와 동일한 기능을 제공하기 때문이다. 우리는 Member를 정의할 때, Object 클래스의 equals()메서드를 오버라이딩하지 않았기 때문에 단순 객체의 참조값을 비교하게 된다. 때문에 에러가 발생하는 것이다.

case3 의 경우는 성공할 것이다. 맴버변수 name은 String 타입이다. String은 equals() 함수를 오버라이딩 해서 실제 값을 비교하도록 구현돼있다. memberA, memberB는 동일한 member라는 이름을 가지기 때문에 성공한다.

case4 의 경우도 String 타입이기 때문에 실제 값을 비교하여 성공하게 될 것이다.

isInstanceOf()

이 메서드는 대상이 특정 클래스의 인스턴스인지 검증할 때 사용한다. 사용법은 assertThat(a).isInstanceOf(b.class)와 같이 사용하면 된다.
아래 예시 코드를 보자

img1

isNull(), isNotNull()

이름 그대로 대상이 null인지 아닌지 확인하는 메서드이다.
바로 예시를 보자

img1

contains(), containsExactly()

contains()는 리스트에 특정 원소가 포함됐는지 확인할 때 사용한다. 순서를 따지지 않고 값만 존재한다면 통과한다.
사용방법은 Assertions.assertThat(list).contains(1, 2)와 같다.

containsExactly()는 contains()와 달리 원소의 순서, 개수까지 정확하게 동일해야 통과를 한다.
아래 코드를 보고 어떤 결과가 나올지 생각해보자.

img1

case1의 경우는 실패할 것이다. containsExactly()는 정확하게 값이 일치하고 순서도 같아야 하기 때문이다.

case2는 성공할 것이다. 순서와 값이 일치한다.

case3은 성공할 것이다. contains는 값의 일부만 일치해도 통과가 된다. 그리고 순서도 신경쓰지 않기 때문이다.

case4는 실패할 것이다. 값은 모두 일치하지만 순서가 다르기 때문이다.

오늘은 기본적인 단위 테스트에 대해서 정리해봤다. 혹시 잘못된 부분이 있다면 알려주세요~

참고 사이트

  • https://m42-orion.tistory.com/97?category=1085496

  • https://tecoble.techcourse.co.kr/post/2021-05-25-unit-test-vs-integration-test-vs-acceptance-test/

  • https://velog.io/@chori/JUnit-5-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4

  • https://inkyu-yoon.github.io/docs/Language/Spring/IsEqualIsSame

  • https://bcp0109.tistory.com/317