MockMVC

1 minute read

드디어 테스트 코드를 짜본다!

TDD 책을 읽을 때까지만 해도 뭐 별거 없네, 해보면 되겠네. 라고 생각했다. 하지만 언제나 그렇듯 현실은 녹록지 않다. 엄청 어려운 피처를 개발하는 것도 아님에도 어떤 테스트 케이스를 작성할지 고민하는데 시간이 많이 걸렸고 테스트 코드를 작성하는 것도 오래 걸렸다. 그 과정에서 MockMVC를 사용하기 위한 세팅 과정에서 꽤 애를 먹었는데, 그 과정을 이번 포스트에서 작성해 보려고 한다.

MockMVC 란?

MockMVC란 Spring MVC 테스트 유틸리티 클래스. 테스트 코드를 작성하지 않는다면 Postman 등의 request를 발생시킬 수 있는 도구를 사용해 직접 호출해 서버를 디버깅해야 하는데 MockMVC를 사용하면 이 과정을 건너뛸 수 있다. 쉽게 말해 Controller를 호출해 주는 도구이다.

@SpringBootTest와 @WebMvcTest

찾아보니 @WebMvcTest와 @SpringBootTest 어노테이션을 사용하는 두 가지 세팅 방법이 존재한다. 둘 다 컨트롤러를 테스트할 때 사용한다. @SpringBootTest는 ApplicationContext 전체를 불러온다. 즉, Bean으로 등록된 객체를 모두 메모리에 올린다. @WebMvcTest는 테스트에 필요한 레이어만 지정할 수 있다. 즉 테스트에 필요한 Bean을 직접 세팅해 사용한다. 우선 이번 포스팅에선 @SpringBootTest를 사용한 테스트에 대해 설명한다.

샘플 코드

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

    @Autowired
    MockMvc mockMvc;

    @Autowired
    WebApplicationContext webApplicationContext;

    @Before
    public void setUp() {
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
                .alwaysDo(print())
                .build();
    }

    @Test
    public void testCodeSample() throws Exception {
        mockMvc.perform(get("/address")
                        .param("param_1", "0"))
                .andExpect(status().isOk())
                .andExpect(content().string("Need reponse text"))
                .andReturn();
    }
    
    . . .
}

@RunWith

JUnit 프레임워크의 테스트 실행 방법을 확장할 때 사용하는 어노테이션. WebApplicationContext를 생성, 관리하는 작업을 해당 어노테이션 안에 선언된 클래스로 이용한다는 의미.

JUnit 5.x 부터는 @RunWith가 아닌 @ExtendWith를 사용한다.

@AutoConfigureMockMvc

MockMVC 사용에 필요한 의존성을 제공한다. 위 샘플 코드처럼 해당 어노테이션을 선언 후 MockMVC를 주입받아 사용한다.

@Before, setUp()

테스트 함수 실행전 공통으로 적용할 요소들을 셋업한다. alwayDo(print()) 체이닝 함수는, 모든 테스트 함수마다 결과를 자세하게 출력하게끔 설정해 놓은 것이다.

JUnit 5.x에서는 @BeforeEach를 사용한다. @After, @AfterEach는 실행후 처리에 대해 지정할 수 있다.

@Test, mockMvc.perform()

@Test 어노테이션은 해당 함수가 테스트 함수임을 의미한다. perform()부터는 본격적인 테스트 코드이다. perform()에는 request method와 주소를 파라미터로 넣어준다. param(), content() 함수를 체이닝해 필요한 파라미터를 세팅할 수 있고 accept(), contentType()의 체이닝 함수를 사용해 필요와 목적에 따라 RequestBuilder를 사용할 수 있다.

  1. get(“/address”).param()
  2. post(“/address”).content()

andExpect()

perform()으로 발생한 요청에 대한 응답 어떤 기대값을 가져야하는지 지정한다.

var response = mockMvc.perform(get("/address")
                        .param("parma_1", "0"))
                .andExpect(status().isOk())
                .andExpect(content().string("Need reponse text"))
                .andDo(print())
                .andReturn();

위 샘플 코드는 Http Response Code가 200인지, 응답 content에 “Need reponse text” 문자열이 있는지 검증한다. 또한 andExpect(jsonPath(“$.field”).value(“success”))처럼 응답 JSON의 특정 경로에 원하는 값이 있는지 확인 가능하다.

andDo(), andReturn()

MockMVC.perform()으로 리턴되는 ResultAction 인터페이스에 대한 처리를 지정한다. 보통 andDo(print())를 많이 쓰는데, 많이 쓰는 만큼 @Before와 setUp() 함수에서 미리 지정해놓으면 편하다. andReturn()은 응답 객체를 그대로 재사용할 수 있도록 해준다.

Leave a comment