Spring

Spring - MockMvc

jaewoo 2023. 4. 3. 23:06

MockMvc

-스프링에서 제공하는 테스트 도구 중 하나로, 컨트롤러의 테스트를 지원하는 모듈이다. MockMvc를 사용하면 서버를 띄우지 않고도 컨트롤러의 동작을 테스트할 수 있다.

-MockMvc는 브라우저에서 요청을 보낼 떄와 동일한 방식으로 HTTP 요청을 생성할 수 있으며, 이를통해 컨트롤러의 응답 결과를 검증할 수 있다.

또한 MockMvc를 사용하여 컨트롤러에서 사용되는 다른 빈들을 Mock객체로 대체하여 테스트를 진행할 수 있다.

-MockMvc 클래스에서 가장 중요한 역할을 하는 메서드,는 perform()이다. 메서드의 선언부는 테스트 대상에 HTTP 메시지를 요청(RequestBulder)하고 실행 결과를 ResultActions에서 확인할 수 있다.

 

해당 perform 메소드는 인자로 RequestBuilder 인터페이스를 받는다. HTTP 요청 객체를 만드는 기능을 제공한다.

 

 

1. GET

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private UserService userService;

@Mock과 @MockBean의 차이 MockBean은 Mock애노테이션과 비슷하게 동작하지만 ApplicationContext에 등록된다. MockBean 을 사용하면 목 객체를 생성하면서 ApplicationContext에 등록되므로 결국 해당 빈을 사용하는 다른 빈들과 연결 될 수 있다.

@Mock은 단위테스트에 주로 사용되고, @MockBean은 통합테스트에서 사용된다는 것이다.

@Test
public void testGetAllUsers(){

		List<UserDto> userList = Arrays.asList(
        			new UserDto("1","Kim"),
                    new UserDto("2","Woo")
                    );
        
        given(userService.getAllUsers()).willReturn(userList);
        
        mockMvc.perform(get("/users"))
        		.andExpect(status().isOk())
                .andExpect(content().contentType(MediaType.APPLICATION_JSON))
                .andExpect(jsonPath("$[0].id",is("1"))
                .andExpect(jsonPath("$[1].name").value("Kim"));
}

 

- given

Mockito에서 given() 메서드는 Stubbing을 위해 사용된다. Stubbing은 테스트 코드에서 호출되는 메서드에 대한 응답을 미리 정의해 놓는 것을 말한다. 즉 메소드가 호출될 때 반환되는 값을 미리 정해두고 테스트를 진행할 수 있게 해주는 것이다.

given 메서드는 원래

given(mockedObject.someMethod()).willReturn(someValue);

해당 형태로 사용되는데 여기서 mockedObject는 Mock 객체를 의미한다 위에 Mvc 테스트 코드에서는 UserService가 @MockBean으로 선언되어 목 객체로 사용된다. willReturn은 해당 메소드가 호출될 때 반환될 값을 정의하는 메소드이다. 

 

여기서 MockBean 으로 선언되면 다른 스프링 빈과 무엇이 다를까?

스프링 빈은 ApplicationContext에 저장되면 실제 데이터베이스나 다른 외부 시스템과 상호작용하여 데이터를 가져오거나 저장하고 수정한다. 이러한 객체를 테스트 환경에서 그대로 사용해버리면 테스트 환경과 실제 운영환경이 다르기 때문에 예상치 못한 오류가 발생할 수 있다. 

반면에 @MockBean을 사용하여 목객체를 등록하면 해당 목 객체는 실제 데이터베이스나 다른 외부 시스템과 상호작용하지 않는다. 이를 통해 테스트 환경에서도 일관도니 결과를 얻을 수 있으며 특정한 데이터베이스나 외부 시스템에 의존하지 않아도 테스트를 진행할 수 있다.

 

perform

위에서는 statis 임포트하여 사용했지만 기존에 적히는 코드는 아래 코드처럼 적힌다.

mockMvc.perform(MockMvcRequestBuilders.get("/user"))
		.contentType(MediaType.APPLAICATION_JSON)
        .param("id","1234")
        .andExpect(MockMvcResultMatchers.status().isOk())
        .andExpect(MockMvcResultMatchers.jsonPath("$.name").value("Kim"))
        .andExpect(MockMvcResultMatchers.jsonPath("$.age").value(30));

 

요청을 보낼 때는 MockMvcRequestBuilders를 사용하고 응답 확인은 MockMvcResultMatchers를 통해확인한다.

만약 리스트로 데이터가 응답한다면 

//해당 리스트의 사이즈
mockMvc.perform(MockMvcRequestBuilders.get("/user"))
		.andExpect(MockMvcResultMatchers.jsonPath("$",Matchers.hasSize(2)));
         .andExpect(MockMvcResultMatchers.jsonPath("$[0].name").value("Kim"));
         //배열 첫번째 인덱스

 

 

2. POST

 

MockMvc를 사용하여 POST 요청을 보내는 방법은 MockMvcRequestBuilders 클래스의 post() 메서드를 사용하면 된다. (RESTAPI이기 때문에 contentType json 설정 필요)

new User("Kim",30) 해당 데이터를 날릴 경우(REST API에 @RequestBody - JSON으로 받아야함)

mockMvc.perform(MockMvcRequestBuilders.post("/user/save")
					.contentType(MediaType.APPLICATION_JSON)
                    .content("{\"name\": \"John\", \"age\": 30}"))
            .andExpect(MockMvcResultMatchers.status().isOk())
            .ansExpect(jsonPath("$.name").value("Kim"))
            .andExpect(jsonPath("$.age").value(30));

 

'Spring' 카테고리의 다른 글

Spring - Feign Client  (0) 2023.04.24
AWS - 배포와 기록(Spring boot)  (0) 2023.04.14
Spring - Filter  (0) 2023.03.30
Spring - DispatcherServlet  (0) 2023.02.24
Spring - 작성자 체크하기  (0) 2023.02.09