[JUnit] MockMvc

반응형

이번글에서는 MockMvc를 사용해 RestController를 test하는 방법에 대해 알아보도록 하겠습니다.

1. RestController

먼저 이번 글에서 사용할 RestController를 아래와 같이 생성했습니다. 별다른 내용없이 GET으로 "/hello"를 호출하면, "Hello World"를 return 해주는 API입니다.

HelloResource

@RestController
@RequestMapping("/hello")
public class HelloResource {

    @GetMapping
    public String helloWorld(){
        return "Hello World!";
    }

}

2. Get API Test

이제 위에서 작성한 GET API를 테스트 해보겠습니다.

2-1) Test String

이전글들의 방법과는 다르게 test에서 RestController의 API를 호출하기위해선 MockMvc를 사용해야합니다. 사용방법은 아래와 같습니다.

HelloResourceTest

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
class HelloResourceTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void testHelloWorld() throws Exception{
        mockMvc.perform(
                get("/hello"))
                .andExpect(status().isOk())
                .andExpect(content().string("Hello World"));
    }

}

소스를 살펴보면 MockMvc 인스턴스는 @Autowired를 통해 주입받아 사용합니다. 이때 Test 클래스에 선언한 @AutoConfigureMockMvc가 위에서 작성한 RestController인 'HelloResource'를 찾아서 Mocking 합니다.

다음으로 @Test에서는 주입받은 MockMvc를 통해 GET API를 호출합니다. 호출방법은 MockMvcRequestBuilders를 통해 호출하고자하는 API를 명시하고, andExpect를 통해 Assert할 결과값을 작성하면 됩니다.

위의 testHelloWorld 테스트는 "/hello"를 GET으로 호출하고 결과값으로 OK Status와 "Hello World!"가 return 되는지를 Assert Test 합니다.

테스트 해보겠습니다.

image.png

테스트가 실패했습니다. Expected 기대값은 "Hello World"인데, 실제론 "Hello World!"를 return 했습니다. "!"가 빠져 있었네요 😅! 다시 한번 테스트해보겠습니다.

image.png

테스트가 통과했습니다. 👏👏👏

위와 같이 MockMvc를 사용해 프로젝트 내부에서 작성한 RestController를 테스트할 수 있습니다.

2-2) Test Json

이번에는 JSON을 return하는 GET API를 테스트 해보겠습니다.

앞선 예제와 동일하게 RestController에 Json 값을 return 하는 GET API를 아래와 같이 작성합니다.

이때 JSON Object로는 Hello라는 class를 사용하도록 하겠습니다. 또한, return 하는 data type을 JSON이라고 명시하기위해 produces 변수에 'MediaType.APPLICATION_JSON_VALUE'을 할당하였습니다.

HelloResource

@RestController
@RequestMapping("/hello")
public class HelloResource {

    @GetMapping(value = "/json", produces = MediaType.APPLICATION_JSON_VALUE)
    public Hello json(){
        return new Hello("Greetings", "Hello World");
    }

    private  class Hello {
        private String title;
        private String value;

        public Hello(String title, String value) {
            this.title = title;
            this.value = value;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }

        public String getTitle(){
            return title;
        }

        public void setTitle(String title){
            this.title = title;
        }
    }
}

다음으로는 test code를 아래와 같이 작성합니다.

HelloResourceTest

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
class HelloResourceTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void helloWordlJson() throws Exception{
        mockMvc.perform(
                get("/hello/json").accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.title", Matchers.is("Greetings")))
                .andExpect(jsonPath("$.value", Matchers.is("Hello World")));
    }
}

이전 예제와 동일하게 MockMvc를 사용해 RestController의 GET API를 호출하도록 작성하였습니다.

다른점으로는 accept(MediaType.APPLICATION_JSON)를 작성함으로써, 오직 JSON 데이터 타입의 return값만 accept 하도록 작성했습니다. return한 JSON 값을 Assert test 하기위해선 jsonPath를 위와 같이 사용하면 됩니다.

테스트 해보겠습니다.

image.png

테스트를 통과했습니다. 이로써 우리는 GET API로 return 받은 JSON 값도 검사할 수 있게 되었습니다. 👏👏👏

2-3) Test Return Data Size

만약 return한 결과값에 대한 Size를 검사하고 싶은경우에는 아래와 같이 작성하면 됩니다. "/hello/json" 호출로 return 하는 Hello Object는 2개의 field를 가지고 있으므로, return 되는 size는 2입니다.

HelloResourceTest

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
class HelloResourceTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void helloWordlJson() throws Exception{
        mockMvc.perform(
                get("/hello/json").accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.*", Matchers.hasSize(2)));
    }
}

테스트 해보겠습니다.

image.png

3. Post API Test

이번에는 POST API를 test 해보도록 하겠습니다.

이전과 동일하게 HelloResource라는 RestController를 아래와 같이 간단히 작성했습니다.

HelloResource

@RestController
@RequestMapping("/hello")
public class HelloResource {

    @PostMapping(value ="/post", consumes = MediaType.APPLICATION_JSON_VALUE
                , produces = MediaType.APPLICATION_JSON_VALUE)
    public Hello post(@RequestBody Hello hello){
        return hello;
    }

    public static class Hello {
        private String title;
        private String value;

        public Hello(){

        }

        public Hello(String title, String value) {
            this.title = title;
            this.value = value;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }

        public String getTitle(){
            return title;
        }

        public void setTitle(String title){
            this.title = title;
        }
    }
}

소스를 살펴보면 "/hello/post"를 통해 POST API를 호출하고, 이때 @RequestBody로 전달받은 JSON_VALUE를 Hello Object로 Parsing 해 그것을 그대로 다시 JSON 형태로 return 해주고 있습니다.

이를 테스트하는 코드는 아래와 같습니다.

HelloResourceTest

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
class HelloResourceTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void testPost() throws Exception {
        //language=JSON
        String json = "{\n" +
                "  \"title\" : \"Greetings\",\n" +
                "  \"value\" : \"Hello World\"\n" +
                "}\n";

        mockMvc.perform(
                post("/hello/post")
                .contentType(MediaType.APPLICATION_JSON)
                .content(json))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.title", Matchers.is("Greetings")))
                .andExpect(jsonPath("$.value", Matchers.is("Hello World")))
                .andExpect(jsonPath("$.*", Matchers.hasSize(2)));
    }
}

GET API를 테스트할때와 마찬가지로 MockMvc를 사용해 POST API를 호출하면 됩니다.

이때 GET API와 다른점은, API를 통해 전달할 content를 같이 명시해줘야한다는 점입니다. 저는 @RequestBody에 JSON 형태로 값을 전달할 것이므로 contentType으로 APPLICATION_JSON을 명시하였으며, 실제 content는 String으로 작성한 json을 사용하였습니다.

API 호출뒤 기대하는 결과값은 GET API와 동일하게 andExpect를 사용해 작성해주면 되겠습니다.

테스트 해보겠습니다.

image.png

테스트를 통과했습니다 😎. 이로써 우리는 MockMvc를 사용해 POST API도 테스트할 수 있게 되었습니다.


참고 자료 : [ https://www.youtube.com/watch?v=8S8o46avgAw&t=956s, https://www.youtube.com/watch?v=Ijj5RLSAcYw&t=5s ]


추천서적

 

자바와 JUnit을 활용한 실용주의 단위 테스트

COUPANG

www.coupang.com

파트너스 활동을 통해 일정액의 수수료를 제공받을 수 있음


반응형

'JUnit' 카테고리의 다른 글

[JUnit] Spy  (0) 2020.08.20
[JUnit] Bad Test  (0) 2020.08.20
[JUnit] Mock & Mockito -2  (0) 2020.08.20
[JUnit] Mock & Mockito -1  (0) 2020.08.20
[JUnit] Stub  (0) 2020.08.20

댓글

Designed by JB FACTORY