컨트롤러
@RestController
public class SampleController {
@GetMapping("/hello")
public String hello(){
return "hello";
}
}
테스트 코드
@RunWith(SpringRunner.class)
@WebMvcTest
public class SampleControllerTest {
@Autowired
MockMvc mockMvc;
@Test
public void hello() throws Exception{
this.mockMvc.perform(get("/hello")
.andDo(print())
.andExpect(content().string("hello"));
}
}
그런데 이 요청을 다음과 같이 보낸다고 해보자.
@RestController
public class SampleController {
@GetMapping("/hello/{name}")
public String hello(@PathVariable("name") String name){
return "hello " + name();
}
}
@RunWith(SpringRunner.class)
@WebMvcTest
public class SampleControllerTest {
@Autowired
MockMvc mockMvc;
@Test
public void hello() throws Exception{
this.mockMvc.perform(get("/hello")
.param("name", "spring"))
.andDo(print())
.andExpect(content().string("hello spring"));
}
Formatter
Formatter를 사용하면 문자열을 객체로 받을 수 있다.
@RestController
public class SampleController {
@GetMapping("/hello/{name}")
public String hello(@PathVariable("name") Person person){
return "hello " + person.getName();
}
}
public class Person {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
그러나 여기서 테스트는 실패한다. 스프링 MVC가 문자열을 Person으로 어떻게 바꿀지 모르기 때문이다. 그걸 알려줄 수 있는 것이 Formatter이다.
public class PersonFormatter implements Formatter<Person> {
@Override
public Person parse(String text, Locale locale) throws ParseException {
Person person = new Person();
person.setName(text);
return person;
}
@Override
public String print(Person object, Locale locale) {
return object.toString();
}
}
Formatter를 등록하는 방법
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addFormatter(new PersonFormatter());
}
}
또한 PathVariable 말고 RequestParam도 동작한다.
@RestController
public class SampleController {
@GetMapping("/hello")
public String hello(@RequestParam("name") Person person){
return "hello " + person.getName();
}
@RunWith(SpringRunner.class)
@WebMvcTest
public class SampleControllerTest {
@Autowired
MockMvc mockMvc;
@Test
public void hello() throws Exception{
this.mockMvc.perform(get("/hello")
.param("name", "spring"))
.andDo(print())
.andExpect(content().string("hello spring"));
}
}
그러나 스프링 부트에서는 Formatter가 빈으로 등록이 되어 있으면 FormatterRegistry에 등록을 하지 않아도 된다.
@Component
public class PersonFormatter implements Formatter<Person> {
@Override
public Person parse(String text, Locale locale) throws ParseException {
Person person = new Person();
person.setName(text);
return person;
}
@Override
public String print(Person object, Locale locale) {
return object.toString();
}
}
@Configuration
public class WebConfig implements WebMvcConfigurer {
}
그런데 테스트는 깨진다. 테스트 코드의 @WebMvcTest 어노테이션은 웹과 관련된 빈만 등록해주기 때문이다.(@Component) 따라서 @SpringBootTest 어노테이션으로 바꾸면 모든 빈을 등록해준다. 하지만 이렇게 되면 MockMvc를 자동으로 빈으로 등록해주지 않기 때문에, @AutoConfigureMockMvc 어노테이션을 추가해줘야 한다.
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class SampleControllerTest {
@Autowired
MockMvc mockMvc;
@Test
public void hello() throws Exception{
this.mockMvc.perform(get("/hello")
.param("name", "spring"))
.andDo(print())
.andExpect(content().string("hello spring"));
}
}
포매터 추가하는 방법 1
포매터 추가하는 방법 2 (스프링 부트 사용시에만 가능 함)
참고