728x90

🔍 1. Mock이란?

✅ Mock은 "가짜 객체"를 말해

  • 실제 의존 객체(여기선 ItemMapper)를 진짜로 실행하지 않고도,
    테스트하고 싶은 코드(MyBatisItemRepository)만 단위로 따로 떼서 테스트할 수 있도록 도와주는 가짜 객체야.

 


package io.shi.dao.dao.mybatis;

import io.shi.dao.global.entity.Items;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import static org.junit.jupiter.api.Assertions.*;

@Slf4j
@ExtendWith(MockitoExtension.class)
class MyBatisItemRepositoryTests {

    @Mock
    ItemMapper mapper;
    MyBatisItemRepository repository;

    @BeforeEach
    void init(){
        repository = new MyBatisItemRepository(mapper);
    }

    @Test
    @DisplayName("상품등록서비스")
    void item_save_test() throws Exception {

        repository.save(null);

    }

}

 

📦 지금 코드 기준으로 설명하면:

@Mock
ItemMapper mapper;

이건 진짜 DB와 연결된 MyBatis Mapper 객체가 아니라,
“이름만 ItemMapper처럼 생긴” 가짜(Mock) 객체를 생성한 거야.
이 가짜 객체는 내부적으로 아무 일도 하지 않고, 원하는 동작을 미리 정의해서 테스트 용도로만 사용해.

 

 


🔁 실제 흐름 분석

repository = new MyBatisItemRepository(mapper);
  • 여기서 mapper는 진짜가 아니라 Mockito가 만든 가짜야.
  • 이걸 MyBatisItemRepository에 주입함으로써, 테스트에서는 DB와 연결 없이 테스트가 가능해.

 

 


💥 Mock을 쓰는 이유

예시: 실제 DB 없이 테스트하기

만약 ItemMapper가 진짜라면, 내부에서 INSERT, SELECT 같은 DB 쿼리가 실행돼야 해. → 근데 테스트 환경에서 매번 DB와 연결하면 느리고, 복잡하고, 데이터도 꼬일 수 있음.

그래서 우리는 ItemMapper를 가짜로 만들어서 이런 DB 호출 없이도 repository 로직이 잘 작동하는지만 테스트할 수 있어.

 

 


🔧 @ExtendWith(MockitoExtension.class)

@ExtendWith(MockitoExtension.class)

이건 JUnit5에 Mockito 기능을 연결해주는 어댑터야.

  • 이걸 붙여야 @Mock 같은 어노테이션이 제대로 작동돼.
  • 없으면 @Mock으로 만든 객체가 주입되지 않아서 NullPointerException이 뜨게 돼.

 

 


🔍 Mock vs Stub vs Spy (간단 정리)

종류 설명 사용 예
Mock 가짜 객체. 테스트 목적의 빈 껍데기 지금 코드의 @Mock ItemMapper
Stub 특정 상황에서 특정 값을 리턴하도록 정의 when(mapper.save(any())).thenReturn(something)
Spy 진짜 객체를 감싸면서 일부만 가짜로 바꿈 실제 객체의 동작 확인 또는 부분 mocking

 

 


🧪 너 코드에서 실제 테스트는?

@Test
@DisplayName("상품등록서비스")
void item_save_test() throws Exception {
    repository.save(null);
}

이건 아직 검증은 안 들어간 상태고, 그냥 null을 넘기고 있어.
보통 이렇게 작성하지 않고, 아래처럼 동작을 지정해줘야 해:

예시

 
@Test
@DisplayName("상품등록 성공 테스트")
void item_save_test() throws Exception {
    Items dummyItem = Items.builder()
        .itemCode("ITEM_123")
        .name("사과")
        .price(1000)
        .build();

    // stub: mapper.save()가 호출되면 아무것도 안 하도록 처리 (void라면 doNothing)
    repository.save(dummyItem);

    // 이후에 mapper.save(dummyItem)이 정말 호출되었는지 검증할 수 있음
    verify(mapper).save(dummyItem);
}

 


✅ 요약

요소 설명
@Mock ItemMapper의 가짜 객체를 생성
MockitoExtension Mockito의 기능을 JUnit5에서 활성화
Mock을 쓰는 이유 DB 없이도 repository 로직만 독립적으로 테스트 가능
verify() mock 객체가 호출됐는지 검증 가능 (테스트 정확도 ↑)

 

 

 


 

728x90

'프로그래밍 > Spring' 카테고리의 다른 글

JPA- 4월 10일  (0) 2025.04.10
Mock란? - 4월 10일  (1) 2025.04.10
MyBatis란?  (0) 2025.04.09
🌟 트랜잭션(Transaction) 이란?  (0) 2025.04.09
JDBC를 이용한 간단한 CRUD 구현  (0) 2025.04.08