spring

Mockito

devJK93 2025. 4. 7.

 

Mockito는 테스트할 때 자주 쓰이는 Mock 객체 생성용 라이브러리다.


1️⃣ Mock 객체란?

Mock 객체는 말 그대로 가짜 객체다.

실제 객체처럼 동작하지만, 내부 로직은 없고 우리가 원하는 대로 행동을 지정할 수 있다. 즉, "흉내만 내는 객체"다.

 

📝 예시:

public interface EmailService {
    void sendEmail(String to, String message);
}

 

→ 진짜 구현은 메일을 보내겠지만,
테스트할 땐 진짜 메일을 보내면 안 되니까 Mock 객체로 대체

그럼 "흉내만 낸다"는 건 무슨 뜻일까?

 

// 실제 클래스 (진짜 메일을 보냄)
public class NotificationService {
    public void send(String message) {
        System.out.println("Sending message: " + message);
    }
}
// 테스트 대상 클래스
public class UserService {
    private final NotificationService notificationService;

    public UserService(NotificationService notificationService) {
        this.notificationService = notificationService;
    }

    public void register(String username) {
        notificationService.send("Welcome, " + username + "!");
    }
}

 

이제 위 코드를 테스트한다고 해보자.
진짜 NotificationService를 쓰면 콘솔에 출력되거나 진짜 메일이 보내질 수 있다.
그래서 Mock 객체로 흉내만 내고, 호출됐는지만 확인하는 것.

 

// Mockito로 만든 Mock 객체 예시
import static org.mockito.Mockito.*;

public class UserServiceTest {
    @Test
    void register_shouldSendWelcomeMessage() {
        NotificationService mockNotification = mock(NotificationService.class); // 가짜 생성
        UserService userService = new UserService(mockNotification);           // 주입

        userService.register("minjae");

        verify(mockNotification).send("Welcome, minjae!"); // 호출됐는지 검증
    }
}

📌 실제 객체 vs Mock 객체 비교

구분 실제 객체 Mock 객체 (흉내만 냄)
동작 진짜 일을 함 (메일 발송 등) 아무 동작도 안 함
목적 실제 서비스용 테스트용 (동작 기록만)
메서드 기록 안됨 verify()로 검증 가능
예시 생성 new NotificationService() mock(NotificationService.class)

 

즉, Mock 객체는 진짜 일을 하지 않고 "그런 척만" 하기 때문에
테스트할 때 안전하고 빠르며, 외부 시스템 없이 동작을 검증할 수 있다.


2️⃣ 왜 Mock 객체를 사용할까?

테스트 대상 클래스가 의존하는 외부 객체(서비스, DB 등)를 대체해서:

  • 테스트 속도 빠르게
  • 외부 환경 영향 없이
  • 단위 테스트만 정확하게

예시:

public class UserService {
    private EmailService emailService;

    public void registerUser(String email) {
        // 회원가입 로직
        emailService.sendEmail(email, "Welcome!");
    }
}

이런 상황에서 진짜 메일 보내면 안 되니까
EmailService를 Mock 객체로 대체


3️⃣ Mockito로 Mock 객체 만들기

Mock 객체는 직접 주입하거나, 자동으로 주입하는 방식이 있다.

 

☝️방법 1 - 직접 주입 (생성자나 세터를 통해)

@Mock
EmailService emailService;

@BeforeEach
void setup() {
    userService = new UserService(emailService); // 직접 주입
}

 

✌🏻방법 2 - @InjectMocks 사용 (자동 주입)

@Mock
EmailService emailService;

@InjectMocks
UserService userService;

 

이 경우, UserService 안에 EmailService가 자동으로 주입되도록 설정되는데,

이 기능은 Mockito가 테스트 실행 시 개입할 수 있어야만 동작한다.

 

이 때, 필요한 게 바로 @ExtendWith(MockitoExtension.class)

JUnit5 환경에서 Mockito 어노테이션이 동작하도록 도와주는 어댑터 역할이다.

@ExtendWith(MockitoExtension.class)
class UserServiceTest {

    @Mock
    EmailService emailService;

    @InjectMocks
    UserService userService;

    @Test
    void testRegisterUser() {
        userService.registerUser("test@example.com");

        verify(emailService).sendEmail("test@example.com", "Welcome!");
    }
}

 

만약 @ExtendWith를 붙이지 않으면, @Mock@InjectMocks가 적용되지 않고 null 에러가 날 수 있다.

 

구분 유무 설명
@ExtendWith 없음 Mock 객체 생성 안 됨, null 발생
@ExtendWith 있음 Mockito가 개입해서 어노테이션 자동 처리 가능

📝 프레임워크 vs 라이브러리 차이

구분 라이브러리 프레임워크
제어 흐름 우리가 호출 프레임워크가 우리 코드를 호출
의존성 주입 직접 해야 함 자동으로 해줌
대표 예 Mockito, Lombok Spring, Django

 

Mockito는 우리가 호출해서 써야 하는 라이브러리다.
자동으로 객체를 생성하고 주입해주진 않기 때문에 프레임워크는 아니다.


✅ 정리

  • Mock 객체 = 테스트용 가짜 객체
  • Mockito = Mock 객체를 쉽게 만들도록 도와주는 라이브러리
  • 프레임워크는 객체 생성과 주입을 자동으로 해주는 것 (ex. Spring)

댓글