Mock의 사전적 의미는 '테스트를 위해 만든 모형'을 의미한다.
mocking : 테스트를 위해 실제 객체와 비슷한 모의 객체를 만드는 것
mock-up : 모킹한 객체를 메모리에서 얻어 내는 과정
mockMvc란 실제 객체와 비슷하지만 테스트에 필요한 기능만 가지는 가짜 객체를 만들어서 애플리케이션 서버에 배포하지 않고도 스프링 MVC 동작을 재현할 수 있는 클래스를 의미한다.
mocMvc 를 이용해서 Controller를 테스트 할 수 있다.
웹 환경에서 컨트롤러를 테스트 하려면 반드시 서블릿 컨테이너가 구동되고 DIspatcherServlet객체가 메모리에 올라가야 한다. 서블릿 컨테이너를 모킹하면 실제 서블릿 컨테이너가 아닌 테스트용 모형 컨테이너를 사용하여 간단하게 컨트롤러를 테스트 할 수 있다.
서블릿 컨테이너를 모킹할 떄 두 가지 어노테이션을 사용할 수 있다.
- @webMvcTest : @Controller, @RestController가 설정된 클래스를 찾아 메모리 생성
(@service, @repository 불가능)
- @AutoConfigureMockMvc : @Controller, @RestController, @service, @repository 등이 설정된 클래스들 모두 메모리 생성
메소드명 | 메소드 특징 | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
perform() | 요청을 전송하는 역할. ResultActions 객체를 받으며, 해당 객체는 리턴 값을 검증하고 확일할 수 있는 andExpect()메소드를 제공한다. | ||||||||||||
get("/경로") | Http 메소드(get, post, put, delete) 결정. 인자로 경로를 보내준다 | ||||||||||||
param("key", "value") | "key" = "value" 의 파라미터를 전달 할 수 있다. "key"="value" 파라미터를 여러 개 전달 할 경우 params()를 사용한다. | ||||||||||||
perform() |
응답을 검증하는 역할.
|
||||||||||||
perform() | 요청을 전송하는 역할. ResultActions 객체를 받으며, 해당 객체는 리턴 값을 검증하고 확일할 수 있는 andExpect()메소드를 제공한다. |
pom.xml에 Junit4를 사용하기 위해 spring-boot-start-test를 추가해준다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.7.5</version>
<scope>test</scope>
</dependency>
임포트가 되지 않을 경우 Junit maven을 추가해주어도 된다.
https://mvnrepository.com/ 에서 필요한 dependency를 가지고 올 수 있다.
Controller 테스트에 필요한 객체 생성
mockMvc 를 통한 Controller 테스트를 하기 전 필요한 객체를 생성한다.
Domain, Service, ServiceImpl, Controller
@Data
public class Person {
private String name;
private int age;
}
public interface PersonService {
String hello(String name);
Person getPerson();
List<Person> getPersonList();
}
@Service
public class PersonServiceImpl implements PersonService {
@Override
public String hello(String name) {
return "Hello : " + name;
}
@Override
public Person getPerson() {
Person person = new Person();
person.setName("selffy");
person.setAge(27);
return person;
}
@Override
public List<Person> getPersonList() {
Person person1 = new Person();
person1.setName("selffy");
person1.setAge(27);
Person person2 = new Person();
person2.setName("Nana");
person2.setAge(27);
List<Person> personList = new ArrayList<Person>();
personList.add(person1);
personList.add(person2);
return personList;
}
}
서비스 객체와 도메인 객체를 생성한 후 해당 서비스를 불러올 수 있는 Controller를 생성한다.
테스트 클래스를 생성하기 앞서 서블릿 컨테이너를 어떤 어노테이션이 모킹하냐에 따라 조금 다르다.
@webMvcTest 어노테이션을 활용할 경우, @service 객체를 메모리에 생성할 수 없기 때문에 위에서 생성한 서비스 객체를 사용하지 않고 controller에 필요한 코드를 작성한다.
@RestController
public class PersonController {
@GetMapping("/hello")
public String hello(String name) {
return "Hello : " + name;
}
내용을 입력하세요.
1) @webMvcTest
해당 테스트 실행 결과는 아래와 같다.
@RunWith(SpringRunner.class)
@WebMvcTest
@SpringBootTest
public class BoardControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
public void testHello() throws Exception {
mockMvc.perform(get("/hello").param("name", "셀피"))
.andExpect(status().isOk())
.andExpect(content().string("Hello : 셀피"))
.andDo(print());
}
내용을 입력하세요.
MockHttpServletRequest:
HTTP Method = GET
Request URI = /hello
Parameters = {name=[셀피]}
Headers = []
Body = null
Session Attrs = {}
Handler:
Type = kr.kwangan2.test.controller.BoardController
Method = kr.kwangan2.test.controller.BoardController#hello(String)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 200
Error message = null
Headers = [Content-Type:"text/plain;charset=UTF-8", Content-Length:"14"]
Content type = text/plain;charset=UTF-8
Body = Hello : 셀피
Forwarded URL = null
Redirected URL = null
Cookies = []
@RestController
public class PersonController {
@Autowired
private PersonService service;
@GetMapping("/hello")
public String hello(String name) {
return service.hello(name);
}
Controller를 테스트 하기 위해 src/test/java 패키지에 테스트 클래스를 생성한다.
@service가 주입된 객체의 메모리 또한 생성하기 위해 @AutoConfigureMockMvc 를 임포트한다.
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.MOCK)
@AutoConfigureMockMvc
public class PersonControllerTest4{
@Autowired
private MockMvc mockMvc;
@MockBean
private PersonService service;
@Test
public void testHello() throws Exception{
when(service.hello("selffy")).thenReturn("Hello : sellfy");
mockMvc.perform(get("/hello").param("name", "selffy"))
.andExpect(status().isOk())
.andExpect(content().string("Hello : selffy"))
.andDo(print());
}
테스트 실행 결과는 아래와 같다.
MockHttpServletRequest:
HTTP Method = GET
Request URI = /hello
Parameters = {name=[selffy]}
Headers = []
Body = null
Session Attrs = {}
Handler:
Type = kr.kwangan2.test.controller.BoardController
Method = kr.kwangan2.test.controller.BoardController#hello(String)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 200
Error message = null
Headers = [Content-Type:"text/plain;charset=UTF-8", Content-Length:"14"]
Content type = text/plain;charset=UTF-8
Body = Hello : selffy
Forwarded URL = null
Redirected URL = null
Cookies = []