Mockito 사용법

Mockito 사용 가이드

Mockito는 자바 기반의 단위 테스트 프레임워크로, 객체의 동작을 모의(mock)하여 테스트를 수행할 수 있게 합니다. 이 가이드에서는 Mockito의 주요 기능들을 실용적인 예제와 함께 설명합니다.

1. 모의 객체(Mock) 생성

Mockito를 사용하면 인터페이스나 클래스에 대한 모의 객체를 생성할 수 있습니다. 모의 객체는 원본 클래스의 모든 메서드를 가지고 있지만, 기본 구현은 간단합니다: void 반환 메서드는 아무 작업도 수행하지 않고, 다른 메서드는 null이나 기본 타입의 값을 반환합니다.

모의 객체 생성 방법

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import java.util.List;
import org.junit.jupiter.api.Test;

public class Mockito기본예제 {
    @Test
    public void 모의객체테스트() throws Exception {
        // List 인터페이스에 대한 모의 객체 생성
        List<String> 문자열목록 = mock(List.class);
        
        문자열목록.add("테스트값");
        
        // add 메서드가 한 번 호출되었는지 검증
        verify(문자열목록, times(1)).add("테스트값");
        verify(문자열목록, times(1)).add("다른값");
    }
}

Spring Boot에서의 모의 객체 생성

Spring Boot 테스트 환경에서는 @MockBean 어노테이션을 사용하여 모의 객체를 생성할 수 있습니다.

@MockBean
private 학생서비스 학생서비스인스턴스;

2. 스텁(Stubbing) 기능

스텁은 테스트에 필요한 데이터를 객체에 설정하는 기능으로, 상태 기반(state-based) 테스트에 적합합니다. Mockito의 when().thenReturn() 구문을 사용하여 메서드 호출 시 특정 값을 반환하도록 설정할 수 있습니다.

// 테스트 데이터 생성
List<학생> 학생목록 = new ArrayList<>();
학생 학생1 = new 학생();
학생1.set이름("홍길동");
학생목록.add(학생1);

학생 학생2 = new 학생();
학생2.set이름("김철수");
학생목록.add(학생2);

// 스텁 설정
Mockito.when(학생서비스인스턴스.findAll()).thenReturn(학생목록);

3. 검증(Verify) 기능

Mockito의 verify() 메서드를 사용하여 모의 객체의 메서드가 호출되었는지, 호출 횟수는 어떻게 되는지 등을 검증할 수 있습니다.

// 메서드가 한 번 호출되었는지 검증
verify(학생서비스인스턴스, times(1)).findAll();
// 최소 한 번 호출되었는지 검증
verify(학생서비스인스턴스, atLeastOnce()).findAll();
// 최대 한 번 호출되었는지 검증
verify(학생서비스인스턴스, atMostOnce()).findAll();
// 전혀 호출되지 않았는지 검증
verify(학생서비스인스턴스, never()).findAll();

4. 인수 매처(Argument Matchers)

특정 인수 값보다는 인수의 타입이나 일반적인 조건에 따라 모의 객체를 설정해야 할 때가 있습니다. 이때 Argument Matchers를 사용합니다.

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;

// 모든 Long 타입 인수에 대해 학생 객체 반환
Mockito.when(학생서비스인스턴스.findById(anyLong())).thenReturn(학생객체);
// 모든 타입의 인수에 대해 학생 객체 반환
Mockito.when(학생서비스인스턴스.findById(any())).thenReturn(학생객체);
// 특정 값에 대해 학생 객체 반환
Mockito.when(학생서비스인스턴스.findById(new Long(10))).thenReturn(학생객체);

5. 스파이(Spy) 사용

같은 클래스 내에서 메서드가 다른 메서드를 호출하는 경우, 스파이 기능을 사용하여 특정 메서드만 모의 객체로 대체할 수 있습니다.

@Service
public class 학생서비스Impl implements 학생서비스 {
    public void 테스트메서드(Integer a, Integer b) {
        System.out.println("테스트 메서드 시작");
        
        Integer 합 = 더하기(a, b);
        
        System.out.println("테스트 메서드 종료 = " + 합);
    }
    
    public Integer 더하기(Integer a, Integer b) {
        System.out.println("더하기 메서드");
        return a + b;
    }
}

스파이를 사용한 테스트 코드:

import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest(classes = 학생서비스Impl.class)
class 학생서비스ImplTest {
    
    @Autowired
    private 학생서비스Impl 학생서비스인스턴스;
    
    @Test
    void 테스트메서드테스트() {
        // 클래스에 스파이 적용
        학생서비스Impl 스파이학생서비스 = Mockito.spy(학생서비스인스턴스);
        
        // 테스트 실행
        스파이학생서비스.테스트메서드(3, 4);
        
        // 동일 클래스 내 메서드 호출 검증
        Mockito.verify(스파이학생서비스, Mockito.times(1)).더하기(3, 4);
    }
}

Spring MVC 컨트롤러 테스트 예제

import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;

@SpringBootTest(classes = 학생컨트롤러.class)
@AutoConfigureMockMvc
public class 학생컨트롤러Test {
    
    @Autowired
    private MockMvc mockMvc;
    
    @MockBean
    private 학생서비스 학생서비스인스턴스;
    
    @Test
    public void 전체조회테스트() throws Exception {
        // 테스트 데이터 생성
        List<학생> 학생목록 = new ArrayList<>();
        학생 학생1 = new 학생();
        학생1.set이름("홍길동");
        학생목록.add(학생1);
        
        학생 학생2 = new 학생();
        학생2.set이름("김철수");
        학생목록.add(학생2);
        
        // 스텑 설정
        Mockito.when(학생서비스인스턴스.findAll()).thenReturn(학생목록);
        
        // 테스트 실행
        mockMvc.perform(MockMvcRequestBuilders.get("/학생/전체조회"))
               .andExpect(MockMvcResultMatchers.status().isOk())
               .andDo(MockMvcResultHandlers.print());
        
        // 메서드 호출 검증
        verify(학생서비스인스턴스, times(1)).findAll();
    }
}

의존성 추가

Maven을 사용하는 경우, 다음 의존성을 pom.xml에 추가합니다:

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>4.5.1</version>
    <scope>test</scope>
</dependency>

Gradle을 사용하는 경우, build.gradle에 다음을 추가합니다:

testImplementation 'org.mockito:mockito-core:4.5.1'

태그: Mockito JUnit 단위 테스트 java 스텁

6월 21일 21:59에 게시됨