Spring 환경에선 보통
@RequestParam
,@RequestBody
,@ModelAttribute
을 이용하여 요청받은 데이터를 model 객체에 매핑 시킨다. 하지만 Spring 에서 자체적으로 제공하는 방법으로 매핑이 되지않을때는 따로 formatter나 converter를 만들어줘야 한다
String ↔️ Object 변환시에 사용
Controller에서 @PathVariable
이나 @RequestParam
등으로 받은 String을 객체로 받고 싶을 때 사용할 수 있다
@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.getName();
}
}
Formatter<T>
를 상속받아서 구현한 다음 Configuration으로 등록하면된다
SpringBoot가 아니라면 WebMvcConfigurer를 상속받아서 addFormatter로 추가하면되며, Boot에서는 Bean으로 등록만하면 알아서 추가해준다
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addFormatter(new PersonFormatter());
}
}
@WebMvcTest // Web과 관련된 Bean들만 인식
class SampleControllerTest {
@Autowired
MockMvc mockMvc;
@Test
void helloTest() throws Exception {
this.mockMvc.perform(get("/hello") // /hello 요청이 왔을때
.param("name", "ddings")) // parameter로 /hello?name=ddings
.andDo(print()) // 결과를 출력해라
.andExpect(content().string("hello ddings"));
// 그리고 content는 hello ddings 여야 한다
}
}
Controller 단위테스트시에 @SpringBootTest
는 실제 운영환경 기준으로 모든 Bean들을 등록하기때문에 프로젝트의 규모가 커질수록 오래걸려서 @WebMvcTest
를 이용하는 경우가 많다
이때, @WebMvcTest
는 Web과 관련된 Bean들만 등록시켜주는데 여기에 @Component
는 들어있지 않다
따라서 Boot환경에서 formatter를 @Component로 등록했을때 @WebMvcTest에서는 인식하지 못하기때문에 다음 옵션을 추가해줘야한다
@WebMvcTest(includeFilters = {
@ComponentScan.Filter(type= FilterType.ASSIGNABLE_TYPE
, classes = PersonFormatter.class)
})
S타입을 T타입으로 변경
타입간의 변환 시 표준을 커스터마이징할 수 있는데, 예를 들어 Spring Data JPA에서는 pk 타입을 가지고 해당하는 Object로 변환해주는 Domain Class Converter를 제공해준다
Spring Data JPA - Reference Documentation
Converter는 Converter<S, T>
를 상속받아서 구현하는게 가능하며, Bean으로 등록할때는 애노테이션을 이용하거나 addFormatters()
의 registry에 추가하면된다
디버깅창을 확인해보면 sourceType인 String
에서 targetType인 Person
로 변환해주는걸 확인할 수 있다