/ / Spring MVC Test, MockMVC: Wygodna konwersja obiektów do / z JSON - json, spring-mvc, mockmvc, spring-mvc-test

Spring MVC Test, MockMVC: Wygodna konwersja obiektów do / z JSON - json, spring-mvc, mockmvc, spring-mvc-test

Jestem przyzwyczajony do JAX-RS i chciałbym mieć podobny komfort podczas wysyłania zapytań za pomocą Spring MVC i pracy z odpowiedziami, czyli po stronie klienta w moich testach.

Po stronie serwera (kontrolera) jestem całkiem zadowolony z automatycznej konwersji, tj. Wystarczy po prostu zwrócić instancję obiektu i mieć JSON w wynikowej odpowiedzi HTTP wysyłanej do klienta.

Czy możesz mi powiedzieć, jak obejść ręczny proces konwersji objectInstance do jsonString czy odwrotnie w tych fragmentach? Jeśli to możliwe, chciałbym również pominąć ręczne konfigurowanie typu zawartości.

String jsonStringRequest = objectMapper.writeValueAsString(objectInstance);

ResultActions resultActions = mockMvc.perform(post(PATH)
.contentType(MediaType.APPLICATION_JSON)
.content(jsonStringRequest)
)

String jsonStringResponse = resultActions.andReturn().getResponse().getContentAsString();
Some objectInstanceResponse = objectMapper.readValue(jsonStringResponse, Some.class);

Dla porównania, dzięki API klienta JAX-RS mogę w łatwy sposób wysłać obiekt za pomocą request.post(Entity.entity(objectInstance, MediaType.APPLICATION_JSON_TYPE) i przeczytaj odpowiedź za pomocą response.readEntity(Some.class);

Odpowiedzi:

0 dla odpowiedzi № 1

jeśli masz dużo obiektów odpowiedzi, możeszutwórz ogólną fabrykę mapperów JsonToObject. Można go następnie użyć do wykrycia typu obiektu z odpowiedzi ogólnej (wszystkie obiekty odpowiedzi dziedziczą z tej samej klasy ogólnej) i prawidłowo zareagować / zarejestrować w przypadku złej próby odwzorowania.

Nie mam pod ręką przykładu kodu, ale jako pseudokod:

public abstract GenericResponse {
public String responseClassName = null;
// get/set
}

W kodzie serwera dodaj nazwę rzeczywistego obiektu odpowiedzi do tej klasy.

Fabryka JsonToObject

public ConverterFactory<T> {
private T objectType;
public ConverterFactory(T type) {
objectType = type;
}

public T convert(String jsonString) {
// Type check
GenericResponse genResp = mapper.readValue(result.getResponse().getContentAsString(),
GenericResponse.class);
if (objectType.getClass().getSimpleName().equals(genResp.getResponseClassName())) {
// ObjectMapper code
return mapper.readValue(result.getResponse().getContentAsString(),
objectType.class);
} else {
// Error handling
}
}
}

Myślę, że można by to rozszerzyć, aby było używane z adnotacjami, aby uzyskać więcej magii automatyzacji z odpowiedzią. (zacznij sprawdzać za pomocą BeanPostProcessor)

@Component
public class AnnotationWorker implements BeanPostProcessor {

@Override
public Object postProcessBeforeInitialization(final Object bean, String name) throws BeansException {
ReflectionUtils.doWithFields(bean.getClass(), field -> {
// make the field accessible if defined private
ReflectionUtils.makeAccessible(field);
if (field.getAnnotation(MyAnnotation.class) != null) {
field.set(bean, log);
}
});
return bean;
}
}

Powyższy fragment kodu jest kopiowany z mojego obecnego projektu i wstrzykuje do pól, trzeba to zmienić tak, żeby działał dla metod np ... tam, gdzie jest to potrzebne.

Wdrożenie tego wszystkiego może być trudne i nie można powiedzieć, że to zawsze działa, ale warto spróbować, jeśli nie masz nic przeciwko odrobinie pracy edukacyjnej.