dev_beomgeun
꾸준하게 차근차근
dev_beomgeun
전체 방문자
오늘
어제
  • 분류 전체보기 (170)
    • 전공 (0)
      • 운영체제 (0)
      • 알고리즘 (0)
      • 자료구조 (0)
      • 데이터베이스 (0)
      • 네트워크 (0)
    • 개발 공부 (32)
      • 웹 (6)
      • 리눅스 (4)
      • 머신러닝 (1)
      • 스프링 (17)
      • Git (2)
      • AWS (2)
    • 개발 도서, 강의 (3)
      • 스프링 입문을 위한 자바 객체지향의 원리와 이해 (0)
      • 모든 개발자를 위한 HTTP 웹 기본 지식(김영한.. (2)
      • 스프링 부트와 AWS로 혼자 구현하는 웹서비스 (1)
    • 문제 풀이 (118)
      • 백준 알고리즘 (72)
      • 프로그래머스 알고리즘, SQL (38)
      • Hackerrank SQL (8)
    • 프로젝트 기록 (4)
      • 캡스톤 종합설계 (4)
      • 반려하루 프로젝트 (0)
    • 활동 기록 (12)
      • 네이버 부스트캠프 (7)
      • 취준 & 코테 (4)
      • 소프트웨어 마에스트로 13기 (1)
    • 이것저것 (1)

블로그 메뉴

  • 홈
  • 깃허브
  • 링크드인
  • 방명록

공지사항

인기 글

태그

  • 그래프탐색
  • 기록
  • 부스트캠프
  • 네이버 부스트캠프
  • 백준
  • HackerRank mysql
  • 백준 DP
  • Baekjoon
  • BFS
  • 프로그래머스 SQL
  • dp
  • AI Tech
  • 스프링
  • 일기
  • 프로그래머스
  • 회고
  • Hackerrank
  • c++
  • 반성
  • 서블릿

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
dev_beomgeun

꾸준하게 차근차근

[Junit5, Mockito] Mockito를 이용해서 Void 메서드 Mocking하기
개발 공부/스프링

[Junit5, Mockito] Mockito를 이용해서 Void 메서드 Mocking하기

2022. 10. 5. 19:11
728x90

현재 상황

현재 "반려 하루" 서비스를 개발하면서 Controller, Service, Entity 단위 테스트를 작성하면서 진행하고 있습니다.

 

이전 서비스를 개발하면서 테스트 코드를 작성하지 않았는데, 테스트를 하기 위해 매번 서버를 띄워서 postman으로 요청을 생성하는 건 너무나 비효율적이었습니다.

또한, 서비스 요구사항의 변경에 대처하기 위함이었습니다.

한번, 두번일 경우 기억을 해서 로직을 수정할 수 있지만 계속해서 요구사항이 변경되었을 때 코드를 수정하면서도 잘 동작하는지 믿을 수 없는 상황을 마주쳤습니다.

 

따라서, 테스트 코드를 작성하는 연습을 하고 있습니다.

1. 기능을 개발해도, 요구사항이 지속적으로 바뀌기 때문에 코드 변경으로 인한 발생 가능한 결함을 사전에 예방할 수 있고

2. 테스트 코드 자체로 기능을 설명하는 문서가 될 수도 있고

3. 제가 가정한 상황에서 실패하는 테스트가 정상적으로 동작하는지 확인할 수 있어서 코드에 대한 신뢰성을 얻을 수도 있다고 생각합니다.

4. 그리고 테스트가 통과하면 기분이 좋습니다 ㅎㅎ

 

Mockito를 이용한 단위 테스트

저는 작성한 로직에 대해 검증을 할 수 있도록 Mock 객체를 이용한 단위 테스트를 작성했습니다.

각 객체 간 의존성을 Mock 객체를 이용해서 해결하고 제가 작성한 로직의 상황에 대해서만 정상적으로 동작하는지 확인하기 용이했습니다.

 

이번 포스팅에서 공유할 내용은 @Mock 객체의 void method를 mocking 하는 도중 마주친 문제점에 대해 작성하려 합니다.

Method Mocking

크게 4가지로 나눌 수 있을 것 같습니다.

 

1. Return Non void Type

이 경우는 BDDMockito의 given - willReturn을 이용해서 해당 메서드가 동작하면 해당 객체를 return 할 것이라 mocking 해주면 됩니다.

given(Mocking하는 클래스.메서드(any())).willReturn(반환하는 객체);

2. Non void Type and Throw

given(Mocking하는 클래스.메서드(any())).willThrow / thenThrow (반환하는 객체);

3. Return void Type

 

4. void Type and Throw

 

저는 3, 4번의 케이스였고, 해당 케이스의 테스트를 작성한 과정을 적어보려 합니다.

마주친 상황

Controller 테스트에서 중복 닉네임을 검증하는 API 테스트를 작성하고 있었습니다. 중복되는 닉네임일 경우 Exception을 발생시키는데, 저는 해당 메서드에 대해 테스트 코드를 작성하고 싶었습니다.

// MemberService.java

public void validateMemberNickName(ValidateMemberNicknameRequest dto) {
    if (memberRepository.findByNickName(dto.getNickName()).isPresent()) {
        throw new DuplicateMemberNicknameException();
    }
}

해당 메서드는 예외를 터트리지 않는 경우 리턴 값이 없습니다.

 

Controller 테스트에서 Service의 해당 메서드를 Mocking 한다면?

// MemberControllerTest.java

given(memberService.validateMemberNickName(any()))
	.thenThrow(new DuplicateMemberNicknameException());

아무 생각 없이 given - thenThrow로 했더니 "reason: no instance(s) of type variable(s) T exist so that void confirms to T"의 컴파일 에러가 발생합니다.

 

해결

Void methods can be used with Mockito’s doNothing(), doThrow(), and doAnswer() methods, making mocking and verifying intuitive:

저는 BDDMockito를 이용했으나, BDDMockito는 결국 Mockito를 감싸고 있는 형태입니다.

BDDMockito의 willDoNothing -> Mockito의 doNothing

BDDMockito의 willThrow -> Mockito의 doThrow

 

1. 만약 해당 메서드가 예외를 터트리지 않고 정상 진행되는 테스트를 작성하고 싶다면

willDoNothing - given

willDoNothing()
	.given(memberService).validateMemberNickName(any());

2. 해당 메서드가 예외를 터트리는 테스트를 작성하고 싶다면

willThrow(해당 예외) - given

willThrow(new DuplicateMemberNicknameException())
	.given(memberService).validateMemberNickName(any());

 

해당 메서드들을 이용해서 테스트 코드를 작성하면, void type의 메서드 역시 정상적으로 동작하는 것을 확인할 수 있었습니다.

 

출처

 

https://www.baeldung.com/mockito-void-methods

 

Mocking Void Methods with Mockito | Baeldung

See how to mock methods that return void using Mockito.

www.baeldung.com

https://www.baeldung.com/mockito-exceptions

 

Mocking Exception Throwing using Mockito | Baeldung

Learn to configure a method call to throw an exception in Mockito.

www.baeldung.com

 

728x90
저작자표시 비영리 변경금지 (새창열림)

'개발 공부 > 스프링' 카테고리의 다른 글

[SpringBoot x JPA] Soft Delete #2 Insert (중복, Unique 제약조건, 인덱스의 관점에서)  (0) 2022.10.27
[SpringBoot X AWS S3] AWS S3 PresigendURL 적용하고 업로드해보기  (1) 2022.10.11
[Github Actions] CI 스크립트에 Redis 환경 추가하기  (0) 2022.10.02
[SpringBoot x JPA] Soft Delete #1 Select (해당 Status 조건 추가 조회 방법) - @Where  (1) 2022.09.11
[SpringBoot x JPA] List 초기화에서 Builder 패턴 사용 시 NullPointerException  (0) 2022.08.08
    '개발 공부/스프링' 카테고리의 다른 글
    • [SpringBoot x JPA] Soft Delete #2 Insert (중복, Unique 제약조건, 인덱스의 관점에서)
    • [SpringBoot X AWS S3] AWS S3 PresigendURL 적용하고 업로드해보기
    • [Github Actions] CI 스크립트에 Redis 환경 추가하기
    • [SpringBoot x JPA] Soft Delete #1 Select (해당 Status 조건 추가 조회 방법) - @Where
    dev_beomgeun
    dev_beomgeun
    백엔드 개발을 하며 얻은 지식과 경험을 공유합니다. 현재 카카오페이에서 백엔드 엔지니어로 일하고 있습니다.

    티스토리툴바