Mock
Mock이란?
- Mock-up : 실제 제품이 나오기 전에 내부적으로 사용하기 위한 모형(or 가짜)
- mock : 진짜인 것처럼 보이도록 진짜와 유사한 상황이나 물건, 물질 등을 의미.
- 테스트 세계에서 Mock : 가짜 객체
- Moking : 단테나 슬라이스 테스트 등에 Mock 객체를 사용하는 것.
테스트에서 Mock 객체를 사용하는 이유
-> Mock 객체를 사용하지 않은 슬라이스 테스트 프로세스

슬라이스 테스트라면 MemberController의 메서드만 테스트를 해야 하는데 서비스 계층을 거쳐서 데이터 액세스 계층, DB까지 동 작 흐름이 끝까지 이어졌다가 돌아와야하는데 기존 테스트는 통합 테스트에 가깝다.
슬라이스 테스트의 목적 : 해당 계층 영역에 대한 테스트에 집중하는 것.
-> Mock 객체를 사용한 슬라이스 테스트 프로세스

Controller에서 Service클래스를 호출하는 것이 아닌 MockService 클래스의 메서드를 호출하고 있기 때문에 다른 계층과 단절되어 불필요한 과정을 줄일 수 있다.
Mockito란?
Mockito
Mock 객체를 생성하고 해당 Mock 객체가 진짜처럼 동작하게 하는 역할을 할 수 있게 하는 여러 라이브러리가 있지만 가장 많이 사용되고, Spring Framework 자체적으로도 지원하고 있는 Mocking 라이브러리이다.
Mockito의 Mocking 기능을 이용해서 테스트하고자 하는 대상에서 다른 계층을 단절시켜 오로지 테스트 대상에만 집중할 수 있다.
슬라이스 테스트에 Mockito 적용
Controller의 테스트에 적용
package com.springboot.slice.mock;
import com.springboot.member.dto.MemberDto;
import com.springboot.member.entity.Member;
import com.springboot.member.mapper.MemberMapper;
import com.springboot.member.service.MemberService;
import com.springboot.stamp.Stamp;
import com.google.gson.Gson;
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.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.transaction.annotation.Transactional;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.startsWith;
import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest
@AutoConfigureMockMvc
class MemberControllerMockTest {
@Autowired
private MockMvc mockMvc;
@Autowired
private Gson gson;
// (1)
@MockBean
private MemberService memberService;
// (2)
@Autowired
private MemberMapper mapper;
@Test
void postMemberTest() throws Exception {
// given
MemberDto.Post post = new MemberDto.Post("taekho@gmail.com",
"택",
"010-1234-5678");
Member member = mapper.memberPostToMember(post); // (3)
member.setMemberId(1L); // (4)
// (5)
given(memberService.createMember(Mockito.any(Member.class)))
.willReturn(member);
String content = gson.toJson(post);
// when
ResultActions actions =
mockMvc.perform(
post("/v11/members")
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.content(content)
);
// then
actions
.andExpect(status().isCreated())
.andExpect(header().string("Location", is(startsWith("/v11/members/"))));
}
}
- @MockBean 어노테이션은 Application Context에 등록되어 있는 Bean에 대한 Mockito Mock객체를 생성하고 주입해 주는 역할을 한다.
- 필드에 추가하면 해당 필드의 Bean에 대한 Mock 객체를 생성한 후, 필드에 주입(DI)한다. - Mapper를 DI 받는 이유는 createMember() 에서 리턴하는 Member 객체를 생성하기 위해서임.
- Mapper를 사용하지 않고 Member 객체를 생성해도 되는데 post 변수 재사용을 위해 Mapper로 변환함.
- 실제 createMember() 의 리턴 값엔ㄴ memberId가 포함이 되는데 response의 Location header에 포함이 되어야 해서 memberId를 리턴해 줄 수 있도록 추가함
- Mockito에서 지원하는 Stubbing 메서드
given()은 Mock 객체가 특정 값을 리턴하는 동작을 지정하는 데 사용함.
- Stubbing이란 ?
테스트를 위해서 Mock 객체가 항상 일정한 동작을 하도록 지정하는 것.
서비스 계층에 적용
package com.springboot.slice.mock;
import com.springboot.exception.BusinessLogicException;
import com.springboot.member.entity.Member;
import com.springboot.member.repository.MemberRepository;
import com.springboot.member.service.MemberService;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.BDDMockito.given;
// (1)
@ExtendWith(MockitoExtension.class)
public class MemberServiceMockTest {
@Mock // (2)
private MemberRepository memberRepository;
@InjectMocks // (3)
private MemberService memberService;
@Test
public void createMemberTest() {
// given
Member member = new Member("taekho@gmail.com", "택", "010-1111-1111");
// (4)
given(memberRepository.findByEmail(Mockito.anyString())).willReturn(Optional.of(member)); // (5)
// when / then (6)
assertThrows(BusinessLogicException.class, () -> memberService.createMember(member));
}
}
- Spring을 사용하지 않고 JUni에서 Mockito의 기능을 사용하려면 @ExtendWith(MockitoExtension.class) 를 추가해야함.
- @Mock 어노테이션을 추가하면 해당 필드의 객체를 Mock객체로 생성
- @InjectMocks 어노테이션을 추가한 필드에 @Mock 객체를 포함하고 있음.
- memberRepository Mock 객체로 Stubbing 하고 있다.
-----------------------------------------
@MockBean
은 내부의 리턴값이 null로 다 바뀜
Mockito Stubbing 메서드
| 메서드 | 설명 | 사용 예제 |
| thenReturn | 특정 호출에 대해 지정된 값을 반환하도록 설정합니다. | when(mock.method()).thenReturn(value); when(mock.get(0)).thenReturn("test"); |
| thenThrow | 특정 호출에 대해 지정된 예외를 던지도록 설정합니다. | when(mock.method()).thenThrow(new RuntimeException()); |
| thenAnswer | 호출 시 동적으로 값을 계산하거나 커스텀 로직을 실행할 수 있도록 설정합니다. | when(mock.method()).thenAnswer(invocation -> "dynamic value"); |
| doReturn | void 메서드 또는 특정 상황에서 반환값을 설정할 때 사용합니다. | doReturn(value).when(mock).voidMethod(); |
| doThrow | void 메서드에서 예외를 던지도록 설정합니다. | doThrow(new RuntimeException()).when(mock).voidMethod(); |
| doAnswer | void 메서드 호출 시 동적으로 값을 계산하거나 커스텀 로직을 실행할 수 있도록 설정합니다. | doAnswer(invocation -> { /* custom logic */ }).when(mock).voidMethod(); |
| thenCallRealMethod | Mock 객체의 실제 메서드를 호출하도록 설정합니다. | when(mock.method()).thenCallRealMethod(); |
| thenReturn(...).thenThrow(...) | 여러 호출에 대해 순차적으로 다른 값을 반환하거나 예외를 던질 수 있습니다. | when(mock.method()).thenReturn(value1).thenThrow(new RuntimeException()); |
'공부기록 > Spring' 카테고리의 다른 글
| [Spring Security] OAuth2 (0) | 2025.02.10 |
|---|---|
| [Spring Security] 기본 (0) | 2025.02.04 |
| [Spring] Testing - Hamcrest, 슬라이스 테스트 // 25.01.22 (0) | 2025.01.22 |
| [Spring] Testing 테스팅 - JUnit // 25.01.21 (1) | 2025.01.22 |
| [Spring] Transaction 트랜잭션 // 25.01.20 (0) | 2025.01.21 |