간단한 CRUD를 Junit을 사용해서 테스트해보자.
UserService 내에 사용자 조회, 가입 메소드가 구현되어 있는데,
내가 구현한 메소드들이 제대로 동작하는지 확인하는 테스트 코드를 작성해본다.
@SpringBootTest
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class UserServiceTest {
...
... Test code ...
...
}
@SpringBootTest
스프링부트 어플리케이션 테스트 시 필요한 의존성 제공
사용자 가입, 조회 쿼리 테스트를 위해 전체 컨텍스트를 테스트에 올린다.
@TestInstance
테스트 인스턴스 생성 단위 설정
설정 된 단위로 테스트를 실행한다.
- PER_METHOD(Default)
메소드 단위로 인스턴스 생성
메소드 별로 각각 인스턴스가 생성되어 테스트 시 서로 간섭이 없다.
- PER_CLASS
클래스 단위로 인스턴스 생성
한 메소드가 실행되면 다른 메소드 실행 시 영향을 끼친다.
JUnit은 테스트 순서를 보장하지 않기 때문에
클래스 단위로 인스턴스를 생성하는 경우, 순서를 지정해서 테스트하는 것이 좋다.
@TestMethodOrder
테스트 순서를 명시하는 어노테이션
사용자 가입 테스트 후 이를 조회하는 테스트를 하고자 할 때,
사용자 가입 테스트는 조회 테스트보다 선행되어야 한다.
- MethodName
메소드 명으로 오름차순 정렬, 메소드명이 같다면 파라미터 타입명 오름차순 정렬
- DisplayName
@DisplayName 값으로 오름차순 정렬
@DisplayName("a") 가 @DisplayName("b") 보다 먼저 실행된다.
- OrderAnnotation
@Order 값으로 순서 명시
@Order(1), @Order(2) ...
어노테이션을 표기했다면 이제 소스코드를 작성해보자.
@SpringBootTest
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class UserServiceTest {
private final Logger log = LoggerFactory.getLogger(getClass());
@Autowired
private UserService userService;
private String name;
private Email email;
private String passwd;
@BeforeAll
void setUp() {
name = "test";
email = new Email("test1@gmail.com");
passwd = "1234";
}
}
테스트에 필요한 변수를 선언하고 이를 setup 해준다.
setUp() 메소드는 테스트 시작 전에 수행되어야하므로 @BeforeAll 어노테이션을 붙인다.
@BeforeAll
테스트 시작 전에 실행되어야하는 메소드
Junit에는 @BeforeAll 과 같은 몇 가지 기본적인 어노테이션이 있다.
어노테이션 | 설명 |
@Test | 테스트 메소드를 의미하는 어노테이션으로, 테스트 메소드마다 명시해주어야한다. |
@BeforeEach | 각 테스트 메소드 시작 전에 실행되어야하는 메소드 |
@AfterEach | 각 테스트 메소드 종료 후에 실행되어야하는 메소드 |
@BeforeAll | 테스트 시작 전에 실행되어야하는 메소드 |
@AfterAll | 테스트 종료 후에 실행되어야하는 메소드 |
테스트를 위한 값을 초기화했다면, 테스트 코드를 작성한다.
@SpringBootTest
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class UserServiceTest {
private final Logger log = LoggerFactory.getLogger(getClass());
@Autowired
private UserService userService;
private String name;
private Email email;
private String passwd;
@BeforeAll
void setUp() {
name = "test";
email = new Email("test1@gmail.com");
passwd = "1234";
}
@Test
@Order(1)
void 사용자_추가() {
User user = userService.join(name, email, passwd);
assertThat(user, is(notNullValue())); // null check
assertThat(user.getSeq(), is(notNullValue()));
assertThat(user.getEmail(), is(email));
log.info("Inserted user: {}", user);
}
}
@Test, @Order 어노테이션을 사용하여 첫 번째로 사용자 가입을 테스트한다.
userService 내에 join 메소드를 실행하고
return 받은 User 객체 내의 데이터가 null이 아닌지, 값이 정확한지 등등을 판별한다.
org.hamcrest.MatcherAssert.assertThat
- junit assert method
테스트가 원하는 결과를 제대로 리턴하는지 수행 결과를 판별하는 메소드
- hamcrest
junit assert 메소드보다 읽기 쉽게 테스트 코드를 작성할 수 있는 라이브러리
Hamcrest matcher 를 사용하려면
아래와 같이 assertThat문 뒤에 하나 또는 여러개의 matchers를 사용한다.
assertThat(T actual, Matcher<? super T> matcher)
메소드 | 설명 |
equalTo | 두 오브젝트가 동일한지 판별 |
is | equalTo와 동일하다. 값이 서로 동일한지 판별 가독성있는 코드 작성 가능 아래 세 문장은 동일하다. assertThat(cheese, is(equalTo(smelly))) assertThat(cheese, equalTo(smelly)) assertThat(cheese, is(smelly) |
notNullValue | null인지 아닌지 판별 비교값이 null이 아닌 경우 테스트 통과 아래 두 문장은 동일하다. assertThat(cheese, is(notNullValue())) assertThat(cheese, is(not(nullValue()))) |
테스트 코드
assertThat(user, is(notNullValue()));
assertThat(user.getSeq(), is(notNullValue()));
assertThat(user.getEmail(), is(email));
1. return받은 user 객체가 null이 아니라면 통과
2. user 객체 내의 seq(pk)가 null이 아니라면,
가입 후 새로운 pk가 생성되었다는 의미이므로 테스트 통과
3. user 객체 내의 email이 내가 입력한 데이터와 동일하다면 통과
내가 입력한 데이터로 가입이 완료되었다는 것을 확인할 수 있음
아래와 같이 동일한 방식으로 사용자 조회 테스트 코드도 작성할 수 있다.
import org.junit.jupiter.api.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
@SpringBootTest
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class UserServiceTest {
private final Logger log = LoggerFactory.getLogger(getClass());
@Autowired
private UserService userService;
private String name;
private Email email;
private String passwd;
@BeforeAll
void setUp() {
name = "test";
email = new Email("test1@gmail.com");
passwd = "1234";
}
@Test
@Order(1)
void 사용자_추가() {
User user = userService.join(name, email, passwd);
assertThat(user, is(notNullValue())); // null check
assertThat(user.getSeq(), is(notNullValue()));
assertThat(user.getEmail(), is(email));
log.info("Inserted user: {}", user);
}
@Test
@Order(2)
void 사용자를_아이디로_조회한다() {
User user = userService.findById(6L).orElse(null);
assertThat(user, is(notNullValue()));
assertThat(user.getEmail(), is(email));
log.info("Found by {}: {}", email, user);
}
}
'Spring Boot' 카테고리의 다른 글
Spring Security 인증 처리 (1) Authentication, SecurityContextHolder (0) | 2022.07.23 |
---|---|
Swagger로 API 문서 자동화하기 +JWT 설정 (0) | 2022.05.26 |
JWT 를 간단히 정리해보자 (1) | 2022.05.17 |
[Spring Boot] H2 DataBase (0) | 2022.02.14 |
Spring Container & Bean (2) (0) | 2021.08.30 |