SpringBoot Junit5 단위 테스트 해보기 01.

FFTL:)·2021년 5월 25일
2

SpringBoot Junit5 Test

목록 보기
1/1
post-custom-banner

현재 작성하고 있는 SpringBoot 프로젝트에 테스트 코드를 적용(?)해보려고 합니다.

SpringBoot의 경우에는 junit을 이용하여 test를 진행 하는데 관련 자료를 찾아보던 중 junit4 와 junit5가 꽤나 다르다는 것을 알게 되었습니다. 여기서 저는 junit5를 사용하기 때문에 junit5를 기준으로 공부를 진행해 보았습니다.

일단 테스트는 크게 단위테스트, 통합테스트로 나뉘게 됩니다.

단위 테스트는 프로젝트에 필요한 하나 하나의 기능에 대한 테스트를 각각 진행하는 것을 단위테스트 라고 합니다.

통합 테스트는 여러개의 단위(기능)이 잘 어우러져 전체 플로우가 제대로 동작하는지 확인하는 것을 통합테스트 라고 합니다.

일단 통합 테스트의 경우에는 테스트 클래스에 @SpringbootTest 어노테이션을 이용하여 진행할 수 있는데, 이 어노테이션을 사용하게 될 경우 @SpringBootApplication 을 찾아가서 모든 빈을 스캔하여 로드하게 됩니다.

그래서 자동으로 빈을 주입할 수 있게 되어 테스트에 용이한(?) 장점이 있습니다. 다만 테스트 실행 시 마다 모든 빈을 스캔하는 작업이 진행되고 이는 결코 가벼운 작업이라고는 볼 수 없게 됩니다.

저는 일단 위에서 설명한 통합 테스트는 제외하고 단위 테스트를 진행해 보려 합니다.

  • 이번 테스트에 필요한 Mockito, AssertJ, Junit5는 'org.springframework.boot:spring-boot-starter-test' 종속성과 함께 자동으로 가져오며, Lombok은 따로 추가해주면 좋습니다.

  • 일단 테스트 하고자 하는 Service의 생성자를 제공하여 생성자 삽입을 허용해 놓도록 합니다.

//BoardService.java
@Service
public class BoardService {

    private final BoardRepository boardRepository;
    
    //이 부분을 Lombok의 @RequiredArgsConstructor 를 이용하여 생략이 가능합니다.
    public RegisterUseCase(BoardRepository boardRepository) {
    	this.boardRepository = boardRepository;
    }

    public List<Board> getAllBoard(){
        List<Board> boards = boardRepository.findAll();
        return boards;
    }
    
    ...

생략 후 (lombok의 @RequiredArgsConstructor사용)

//BoardService.java
@RequiredArgsConstructor
@Service
public class BoardService {

    private final BoardRepository boardRepository;

    public List<Board> getAllBoard(){
        List<Board> boards = boardRepository.findAll();
        return boards;
    }
    
	...

위 처럼 세팅을 해놓은 상태로 이제 테스트 코드를 작성합니다.

//BoardServiceTest.java
class BoardServiceTest {

    //1.
    private BoardRepository boardRepository = Mockito.mock(BoardRepository.class);
    private BoardService boardService;

    @BeforeEach
    public void setUp(){
        boardService = new BoardService(boardRepository);
    }

    @Test
    void saveBoard() {
        SaveBoardDto saveBoardDto = new SaveBoardDto("title", "content", "nickname", "2021-03-01", 1L);
        //2.
        when(boardRepository.save(any(Board.class))).then(returnsFirstArg());
        Board board = boardService.saveBoard(saveBoardDto);
        //3.
        assertThat(board.getNickname()).isEqualTo("nickname");
    }
  1. Mockito.mock(BoardRepository.class);
    Mockito.mock을 이용하여 껍데기만 존재하는 BoardRepository를 생성해 냅니다. 이렇게 생성된 boardRepository는 현재 모든 응답에 null을 반환하는 상태입니다.

  2. when(boardRepository.save(any(Board.class))).then(returnsFirstArg());
    when~then을 이용하여 boardService.saveBoard()의 테스트에 필요한 boardRepository.save()의 동작을 지정하여 테스트를 진행할 수 있도록 만들어 줍니다.
    ( any(Board.class) => Board의 객체라면 무엇이든 받을 수 있다. )
    ( returnsFirstArg() => 반환되는 객체의 첫번째 매개 변수를 리턴합니다. 반환되는 객체는 board 하나 뿐 이니까 board가 반환됩니다.)

  3. assertThat(board.getNickname()).isEqualTo("nickname");
    저장되어 반환된 board의 nickname과 입력했던 nickname이 동일 한지 체크하여 성공, 실패를 반환합니다.

인터넷의 자료들을 찾고 찾아서 기록할 겸 작성한 글 입니다. 제가 작성했지만 설명이 부족한 부분도 있을 것이고, 틀린 부분도 있을 수 있습니다. 혹시나 발견하셨다면 댓글로 꼭 알려주세요! 이상입니다.


참고
(갓대희님 블로그)
https://goddaehee.tistory.com/210?category=367461
(reflectoring.io)
https://reflectoring.io/unit-testing-spring-boot/

profile
생각하는 개발자가 되자!
post-custom-banner

0개의 댓글