현재 프로젝트에서 MockMvc를 통해 테스트를 작성하고 있다.
그렇기 때문에 body에 json타입을 넣으려면 ObjectMapper를 통해 기입해줘야한다. (writeValueAsString
)
여기까지는 문제가 없지만 검증할 때 문제가 생기게 된다.
나는 mockMvc.andReturn().getResponse()를 통해 MockHttpServletResponse
를 가져와서 검증하는 것을 선호한다. 이렇게 하면 좀 더 검증부분가 행동부분이 구분이 가서 더 깔끔해지기 때문이다.
하지만 현재 프로젝트는 ApiResponse
@Getter
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ApiResponse<T> {
private T data;
public ApiResponse(T data) {
this.data = data;
}
}
이럴 경우 아래처럼 ObjectMapper의 readValue
로 바로 객체를 반환받을 수 없다.
objectMapper.readValue(response.getContentAsString(), ApiRespone<T>.class)
// 불가능
제너릭은 컴파일타임에서만 타입 파라미터를 확인하고, 이후에는 원래 클래스 타입만 남는 Type Erasure 특징을 가지고 있기 때문에 불가능한 것 이다.
이에 해결법을 찾고자 서칭을 하게 되었고 나와 같은 고민을 한 사람들이 쓴 글을 보게 되었다.
objectMapper.getTypeFactory().constructParametricType()
를 통해 JavaType를 추출하여 형변환을 할 수 있음을 알게 되었다. 추출한 JavaType을 통해 객체로 반환받을 수 있는 것이다.
JavaType javaType = objectMapper.getTypeFactory().constructParametricType(ApiResponse.class, TokenResponse.class);
해당 JavaType을 readValue
를 쓰던 것처럼 사용해주면 된다.
프로젝트에서 자주 사용될 것 같아 메서드로 만들어 안의 data 객체를 가져올 수 있도록 만들었다.
protected <T> T getResponseObject(MockHttpServletResponse response, Class<T> type) throws IOException {
JavaType javaType = objectMapper.getTypeFactory().constructParametricType(ApiResponse.class, type);
ApiResponse<T> result = objectMapper.readValue(response.getContentAsString(), javaType);
return result.getData();
}
저번 프로젝트에서도 해당 문제점이 발생하여 TypeReference
를 사용하여 해결하였지만 이는 메서드로 추출에 실패하여 jsonPath
로 검증했었다.
하지만 사용하면서도 찜찜했던 것이 행동과 검증의 경계점이 모호해진다고 나는 생각이 들었다.
그렇기 때문에 위에서 해결한 방식으로 나는 검증을 해나갈 것 같다.
Reference
'Back-End > Spring' 카테고리의 다른 글
JPA Fetch Join MultipleBagFetchException (0) | 2022.08.20 |
---|---|
JPA exists 쿼리 성능 개선 (0) | 2022.08.20 |
댓글