간단한 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);
    }
}
복사했습니다!