Spring - Mockito

김상엽·2024년 2월 22일
0

Spring

목록 보기
15/26
post-thumbnail

TIL

테스트 코드의 중요성

코드를 개발하면서, 과연 개발한 코드가 정상적으로 작동하는지 테스트를 하는 과정이 동반된다.
나도 프로젝트를 진행하면서 셀 수 없이 테스트를 진행하였다.
테스트를 최대한 자세히, 많이 하여 버그를 줄이는 것이 테스트의 목적이다.
버그를 아예 없애는건 불가능하다.

  • 이 사진은 버그 발견 시간이 늦어짐에 따라 비용이 기하급수적으로 커지는 걸 보여준다.



    실제로 즐겨하고 있는 게임에서도 뒤늦게 확률형 아이템의 로직에 버그가 발견되어서 2년동안의 기간에 대한 환불을 진행했었다.

기존에 내가 하던 테스트

사실 여태까지 진행했던 테스트는 실재로 사용자의 입장이 되어서 직접 값을 입력하거나 하는 형태로만 진행을 했었다.
그에 따라 테스트로 인한 Database에 변화가 항상 이루어졌고,
테스트를 할때마다 DB의 테이블을 Drop하는 과정이 있었다.
이렇게 진행했던 이유는 간단했었다.
테스트 하는 API가 사용자의 입력이나, 사용자의 정보를 받아 객체를 생성하여 다루는데,
객체간의 의존성도 생기면서 단위테스트용 입력이나, 정보를 입력하는 방법을 알지 못했었다.

Mockito


Mockito는 개발자가 동작을 직접 제어할 수 있는 가짜 객체를 지원하는 테스트 프레임워크이다. 
Mockito를 활용하면 가짜 객체에 원하는 결과를 Stub하여 단위 테스트를 진행할 수 있다.

Mockito 사용법

  1. Mock 객체 의존성 주입
    @Mock: 가짜 객체를 만들어 반환해주는 어노테이션
    @Spy: Stub하지 않은 메소드들은 원본 메소드 그대로 사용하는 어노테이션
    @InjectMocks: @Mock 또는 @Spy로 생성된 가짜 객체를 자동으로 주입시켜주는 어노테이션


  2. Stub로 결과 처리
    의존성이 있는 객체는 가짜 객체를 주입하여 어떤 결과를 반환하라고 정해진 답변을 준비시켜야 한다.
    Mockito에서는 다음과 같은 stub 메소드를 제공한다.
  • doReturn(): 가짜 객체가 특정한 값을 반환해야 하는 경우
  • doNothing(): 가짜 객체가 아무 것도 반환하지 않는 경우(void)
  • doThrow(): 가짜 객체가 예외를 발생시키는 경우


    나는 BDDMockito를 사용하여 다음과 같이 결과를 정해주었다.


  1. Mockito와 Junit의 결합
    Mockito도 테스팅 프레임워크이기 때문에 JUnit과 결합되기 위해서는 별도의 작업이 필요하다.
    기존의 JUnit4에서 Mockito를 활용하기 위해서는 클래스 어노테이션으로 @RunWith(MockitoJUnitRunner.class)를 붙여주어야 연동이 가능했다.
    하지만 SpringBoot 2.2.0부터 공식적으로 JUnit5를 지원함에 따라,
    이제부터는 @ExtendWith(MockitoExtension.class)를 사용해야 결합이 가능하다.


    출처: https://mangkyu.tistory.com/145 [MangKyu's Diary:티스토리]

Service 테스트 코드

  • given - when - then의 구조로
    • given : 테스트를 위한 테스트케이스를 만들어주고
    • when : 테스트케이스에 대한 함수를 실행하고
    • then : 함수의 결과가 올바른지 검사하는 형태이다.
      assertEquals(a,b) : 값비교
      assertNotNull(대상, 실패시 메시지) : Null 여부 체크
      assertThrows(Exception.class, () -> 테스트대상 메소드) : 예외 발생 테스트*assertDoesNotThrow(() -> Do) : *예외 발생 X 테스트

Service 테스트 화면

기존에 테스트를 하게되면 Postman이나, 로컬 서버에 접속하여 사용자의 입장이 되어 직접 입력을 하고, 출력되는 값을 보고 코드가 제대로 작동하는지 판단했었다.
Mockito를 통해 간단하게 여러개의 테스트를 진행하고 확인도 간단하게 진행 할 수 있게 되었다.

Controller 테스트

Controller의 테스트의 경우 @WebMvcTest 어노테이션을 통해 진행할 수 있다.

진행했던 프로젝트는 Spring Security를 통해 사용자의 인증과 인가를 진행했기에, 테스트를 위해 가짜 MockSpringSecurityFilter를 만들고, 가짜 사용자 정보도 만들어주고 진행을 하였다.

Controller 테스트 코드


Client에서 오는 입력은 JSON 데이터로 오게되는데,
이를 Dto객체로 맵핑하기위해 objectMapper.writeValueAsString을 사용한다.
그리고 MediaType.APPLICATION_JSON을 통해 JSON 타입임을 알려준다.

Controller 테스트 화면

기존에 테스트를 하기위해 PostmanJWT 토큰과 Body에 JSON 데이터를 직접 입력했었는데,
이제는 손쉽게 테스트 할 수 있게 되었다.

오늘의 회고

저번에 JUnit에 대해 배웠지만 객체가 의존성을 가지게 되면서 사용할 엄두가 나지않아 일일히 수작업으로 사용자의 입장이 되어 테스트를 진행했었다.
View도 구현하지 않아서 Postman으로 JSON 데이터를 직접 타이핑하고,
테스트 할때마다 로그인을 매번해주고, 반환받은 JWT토큰을 매번 복붙해줬었다...

Swagger를 사용했음에도 테스트를 위해 Postman에도 API정리를 강제로 하게 되었다.

하지만 이제는 쉽게 테스트 할 수 있게되어 다행이다.
내일부터 팀 프로젝트 시작이다.
프로젝트를 진행할때마다 성장이 눈에 보여서 이번 프로젝트도 기대가 된다.

profile
개발하는 기록자

0개의 댓글