[Test] Mock을 이용한 단위 테스트(with Mockito)

2025. 10. 1. 14:51·Development/개발 공부

단위 테스트에 대한 내용은 여기로 → 2025.09.27 - [Development/개발 공부] - [Test] 단위 테스트(Unit Test)

 

Mock

Mock은 Test Double(테스트 대역) 중 하나로 테스트 대상이 사전에 정의한 규칙대로 메소드를 호출했는지 확인한다.

Stub은 상태 기반 검증이라면, Mock은 행위 기반 검증이다.

 

Mock은 Stub과 달리, 새 클래스(Stub)를 만들 필요가 없다.

따라서 다양한 시나리오를 손쉽게 추가할 수 있다는 장점이 존재한다.

 

Mock의 수행 과정은 다음과 같다.

 

가짜 객체(Mock)를 생성한다.

↓

생성된 Mock들을 테스트 대상 클래스에 주입한다.

↓

Mock의 동작을 정의한다.

↓

테스트 결과를 예상 결과와 대조한다.


 

Mockito 프레임워크(+ 예제)

Mockito는 단위 테스트를 위한 Java 오픈소스 프레임워크이다.

Mockito 프레임워크는 앞서 설명한 Mock 수행 과정 중 가짜 객체 생성 및 의존성 주입을 어노테이션(@)으로 지원한다.

 

예제를 통해 Mock 테스트 과정을 살펴보자.

먼저 A 클래스는 다음과 같다.

class A {
	private DataService dataService;
    
    public A(DataService dataService) {
    	super();
        this.dataService = dataService;
    }
    
	public int findMaxFromAllData() {
    	int[] data = dataService.retriveAllData();
    	int maxValue = Integer.MIN_VALUE;
        for (int value : data) {
        	if (value > maxValue) {
            	maxValue = value;
            }
        }
        return maxValue;
    }
}

 

A 클래스는 배열 중 가장 큰 값을 return 하는 findMaxFromAllData() 메소드를 가지고 있다.

이제 findMaxFromAllData()를 테스트하기 위한 ATest 파일을 생성하자.

import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
class ATest {

}

 

먼저 테스트 클래스 위에 @ExtendWith(MockitoExtension.class) 를 붙여, Mockito 기능을 연결해준다.

 

그 다음, Mock 객체를 생성해 테스트 클래스에 Mock을 주입해야 한다!

이때 필요한 어노테이션은 @Mock과 @InjectMocks이다.

  • @Mock: Mock 객체를 자동으로 생성해주는 어노테이션
  • @InjectMocks: 생성된 Mock들을 테스트 대상 클래스에 자동으로 주입해주는 어노테이션
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
class ATest {
	@Mock
    private DataService dataServiceMock;
    
    @InjectMocks
    private A a;
}

 

Stub은 테스트하기 위한 값을 가지는 Stub 클래스를 가져야 한다.

또한 테스트 클래스 내에 가짜 구현체(Stub) 인스턴스를 생성하여, 의존성을 주입받아야 했다.

하지만 Mock은 테스트 클래스안에 Mock 객체(dataService)와 테스트 대상 인스턴스(a)만 선언해주면 된다.

 

이제 테스트 메소드를 만들어보겠다.

import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
class ATest {
	@Mock
    private DataService dataServiceMock;
    
    @InjectMocks
    private A a;
    
    @Test
    void findMaxFromAllDataScenario() {
    	when(dataServiceMock.retrieveAllData()).thenReturn(new int[] {25, 15, 5});
        assertEquals(25, a.findMaxFromAllData());
        verify(dataServiceMock, times(1)).retrieveAllData();
    }
}

 

a.findMaxFromAllData() 내부에서 dataService.retrieveAllData()를 호출하면, Mockito가 자동으로 Mock인 int 배열을 반환한다.

반환된 Mock 데이터를 기반으로, 비즈니스 로직이 수행되며 테스트를 진행한다.

verify는 dataServiceMock에서 retrieveAllData()가 1번 호출되었는지 검증한다.

(assert는 결과를 검증하고, verify는 호출을 검증한다!)

 

테스트 결과는 다음과 같다.

 

 

만약, 테스트 시나리오를 추가하고 싶다면 when(...).thenReturn(...)만 바꿔주면,

@InjectMocks가 알아서 테스트할 값을 주입해준다!!


 

List 인터페이스 모킹

메소드를 호출해서 얻는 특정 결과 뿐만 아니라, List 자체의 크기나 상태를 확인할 때도 Mock을 사용할 수 있다.

이때도 다음과 같은 순서대로 행하면 된다.

 

가짜 List 객체(Mock)를 생성한다.

↓

Mock의 동작을 정의한다.

↓

테스트 결과를 예상 결과와 대조한다.

 

테스트 예제 코드는 다음과 같다.

class BTest {
	@Test
    void bTest1() {
    	List listMock = mock(List.class);
        
        when(listMock.size()).thenReturn(3);
        assertEquals(3, listMock.size());
    }
    
    @Test
    void bTest2() {
    	List listMock = mock(List.class);
        
        when(listMock.get(0)).thenReturn("0번째 값!!");
        assertEquals("0번째 값!!", listMock.get(0));
    }
    
    @Test
    void bTest3() {
    	List listMock = mock(List.class);
        
        when(listMock.get(Mockito.anyInt())).thenReturn("어느 숫자든 괜찮아요.");
		assertEquals("어느 숫자든 괜찮아요.", listMock.get(0));
		assertEquals("어느 숫자든 괜찮아요.", listMock.get(1));
    }
}

 

모든 테스트에서는 가짜 List 객체(listMock)를 생성한다.

이후 List에 대한 정보를 임의로 설정해, 행동을 정의한다.

  • bTest1(): listMock의 size를 3으로 정의하여, 3(expectedValue)이 listMock의 size(actualValue)가 맞는지 검증한다.
  • bTest2(): listMock의 0번째 값을 "0번째 값!!"으로 정의하여, "0번째 값"(expectedValue)이 listMock의
                           0번째 값(actualValue)가 맞는지 검증한다.
  • bTest3(): listMock에 int 자료형이 들어오면 "어느 숫자든 괜찮아요"의 반환값을 정의하여,
                          "어느 숫자든 괜찮아요"(expectedValue)가 listMock의 (int 자료형)번째 값(actualValue)가 맞는지 검증한다.

따라서, Mock을 유연하게 활용하기 위해 List 인터페이스를 추가로 이용할 수 있다!

 

👏

 

참고

https://kdh1226.tistory.com/23

https://adjh54.tistory.com/346#1)%20Mockito-1

'Development > 개발 공부' 카테고리의 다른 글

AOP(Aspect Oriented Programming, 관점 지향 프로그래밍)  (0) 2025.11.10
[NoSQL] Redis란?  (0) 2025.10.17
[Test] Stub을 이용한 단위 테스트(with JUnit)  (0) 2025.09.30
[Test] 단위 테스트(Unit Test)  (0) 2025.09.27
WEB / WAS(Web Application Server)  (0) 2025.09.17
'Development/개발 공부' 카테고리의 다른 글
  • AOP(Aspect Oriented Programming, 관점 지향 프로그래밍)
  • [NoSQL] Redis란?
  • [Test] Stub을 이용한 단위 테스트(with JUnit)
  • [Test] 단위 테스트(Unit Test)
jjangsudiary
jjangsudiary
jjangsudiary 님의 블로그 입니다.
  • jjangsudiary
    jjangsudiary 님의 블로그
    jjangsudiary
  • 전체
    오늘
    어제
    • 분류 전체보기 (81) N
      • 이모저모 (0)
        • 회고 (0)
      • Development (17) N
        • 개발 공부 (14) N
        • 프로젝트 (2)
      • Android (10)
        • Compose (1)
      • AI (15)
      • Computer Science (25)
        • 네트워크 (8)
        • 데이터베이스 (10)
        • 운영체제 (6)
        • 자료구조 (0)
        • 컴퓨터구조 (1)
      • Java (9)
        • 디자인패턴 (2)
      • Spring (3)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • GitHub
  • 공지사항

  • 인기 글

  • 태그

    자바
    Python
    백준
    코딩 테스트
    baekjoon
    파이썬
    인공지능
    os
    android
    database
    java
    딥러닝
    Ai
    머신러닝
    TensorFlow
    운영체제
    CS
    안드로이드
    db
    프로그래머스
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
jjangsudiary
[Test] Mock을 이용한 단위 테스트(with Mockito)
상단으로

티스토리툴바