개발에서 테스트는 매우 중요한 부분입니다. 특히 비즈니스 로직을 중점적으로 개발하는 백엔드 개발자에게 있어서 테스트는 언제나 고민이 되는 부분일 것입니다. 그래서 요즈음 TDD(Test-driven Development)
, 테스트 주도 개발이라는 소프트웨어 방법론을 많이 사용하고 있습니다. 간략히 설명하면 단위 테스트 케이스를 작성하고 이를 통과하는 개발 코드를 작성하는 방법입니다.
Spring에서 단위 테스트를 위해 주로 사용하는 프레임워크인 JUnit에 대해 정리해보려고 합니다. 이 글에서는 어노테이션(annotation)
과 Assert
을 중점으로 정리를 할 것입니다.
해당 글에서는 테스트를 위해 Junit5를 사용할 것입니다. Junit5는 이전 버전과 다르게 3개의 서브 프로젝트로 이루어져 있습니다. (JUnit5는 java 8부터 지원합니다.)
JUnit Platform
+ JUnit Jupiter
+ JUnit Vintage
로 이루어져 있습니다.
- JUnit Platform : JVM에서 테스트 프레임워크를 실행하는데 기초를 제공
- JUnit Jupiter : JUnit5에서 테스트를 작성하고 확장을 하기 위한 새로운 프로그래밍 모델과 확장 모델의 조합
- JUnit Vintage : 하위 호환성을 위해 JUnit3와 JUnit4를 기반으로 돌아가는 플랫폼에 테스트 엔진 제공
기본적인 테스트를 작성하기 위한 샘플은 다음과 같습니다.
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
public class ExampleTest {
private final SimpleModel simpleModel = new SimpleModel();
@Test
public void Test(){
assertEquals(2, simpleModel.add(1,1));
}
}
해당 테스트가 정상적으로 이루어지면 다음과 같은 결과가 나옵니다.
테스트가 실패 시에는 아래와 같이 failed라고 알려줍니다.
그리고 테스트 코드 가독성을 높이기 위해 아래와 같은 템플릿에 따라 작성하기도 합니다. (By 스프링 강의)
@Test
public void findByName() {
//given -> 테스트 실행을 위한 조건 설정
Member member1 = new Member();
member1.setName("spring1");
repository.save(member1);
Member member2 = new Member();
member2.setName("spring2");
repository.save(member2);
//when -> 실제로 테스트 하기 위한 코드 작성
Member result = repository.findByName("spring1").get();
//then -> 테스트 결과
assertThat(result).isEqualTo(member1);
}
✅ JUnit Annotation
이제 본격적으로 테스트 코드를 처음 작성해보는 개발자를 대상으로 JUnit에서 자주 사용하는 어노테이션에 대해 알아보자
- @DisplayName : 테스트 클래스나 테스크 메소드에 이름을 붙여줄 때 사용
@Test
@DisplayName("Testing for add function")
public void Test(){
assertEquals(2, simpleModel.add(1,1));
}
- @BeforeEach : 테스트 메소드가 실행되기전에 실행되어야 하는 메소드를 명시해줍니다. 일반적으로 테스트 전에 필요한 데이터를 세팅해주기 위해 주로 사용합니다.
@BeforeEach
public void beforeEach(){
memberRepository = new MemoryMemberRepository();
memberService = new MemberService(memberRepository);
}
- @AfterEach :
@Test
가 붙은 테스트 메소드가 실행되고 난 후 실행됩니다. 일반적으로 테스트 실행 후 초기화를 위해 사용합니다.
@AfterEach
public void afterEach(){
repository.clearStore();
}
- @AfterAll :
@AfterEach
와 다르게 테스트가 완전히 끝난 후 딱 한 번만 실행합니다.
@AfterAll
public static void afterAll(){
//do Something
}
- @BeforeAll :
@BeforeEach
와 다르게 테스트가 시작히기 전 딱 한번만 실행합니다.
@BeforeAll
public static void beforeAll(){
//do Something
}
- @Disabled : 테스트 클래스나 메소드의 테스트를 비활성화 합니다.
@Test
@Disabled
public void disabled_test() {
//do something
}
위에 어노테이션으로 테스트를 실행했을 때 실행되는 순서는 다음과 같습니다.
✅ JUnit Assert
어노테이션과 더불어 중요한 JUnit Assert
에 대해서 알아봅시다. assert는 테스트에 넣을 수 있는 정적 메서드 호출입니다. 각 Assert 구문은 어떤 조건이 참인지 검증하는 방법입니다. 설정한 조건이 참이 아니면 테스트는 실패합니다.
- assertEquals() : 오른쪽의 결과가 왼쪽과 동일한지 확인하는 구문
@Test
public void Test(){
assertEquals(2, simpleModel.add(1,1));
}
- assertTrue() : 해당 함수의 return 값이 true이면 성공
@Test
public void Test(){
assertTrue(true); //true에 특정 함수 삽입
}
- assertTimeout() : 특정 시간동안 테스트가 끝나지 않으면 테스트를 실패시키는 구문
@Test
public void Test(){
assertTimeout(Duration.ofMinutes(1), () -> {
//1분 미만으로 동작되는 함수 실행
});
}
- assertTimeoutPreemptively() : 특정 시간동안 테스트가 끝나지 않으면 테스트를 실패시키는 구문 하지만 위와 다르게 특정 시간이 지나면 테스트를 종료
@Test
public void Test(){
assertTimeoutPreemptively(Duration.ofMinutes(20), () -> {
// 20분 이상 걸리는 작업
});
}
하지만 JUnit Jupiter가 제공해주는 assertion은 많은 테스트 시나리오에는 부족할 수 있기 때문에 JUnit에서 AssertJ ,Truth, Hamcrest와 같은 써드 파티 라이브러리를 쓰는 걸 추천합니다.
'개발 > Spring' 카테고리의 다른 글
[Spring] REST API 리턴 시 원하는 JSON 데이터 반환하기 (0) | 2021.10.08 |
---|---|
[Spring] Repository와 Service 구현하기 (0) | 2021.10.06 |
[Spring] 간단한 Rest API 만들어보기 (0) | 2021.09.27 |
[Spring] Spring 웹 개발 기초 (0) | 2021.08.16 |
[Spring] 프로젝트 생성 (0) | 2021.08.12 |
댓글