我有一个简单的测试,可以在POST
中为RestController
方法编写。当我运行应用程序时,此贴图工作正常。但是,在测试中,我总是得到HttpMessageNotReadableException
和400-Bad Request
。
InternalCustomerController.class
@RestController
@RequestMapping(
value = "/",
consumes = {MediaType.APPLICATION_XML_VALUE},
produces = {MediaType.APPLICATION_XML_VALUE})
@RequiredArgsConstructor
public class InternalCustomerController {
private final CustomerService customerService;
@PostMapping(value = "/cpdupdate")
public Notification updateCustomerProduct(@NotNull @RequestBody Customer customer) {
return customerService.handleUpdateCustomerProduct(customer);
}
}
InternalCustomerControllerTest.class
@RunWith(SpringRunner.class)
@WebMvcTest(controllers = InternalCustomerController.class)
@Import(TestObjectMapperConfig.class)
public class InternalCustomerControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private CustomerService customerService;
@Test
public void testUpdateCustomerProduct() throws Exception {
Customer validCustomer = createValidCustomer("76d211bb680843c5b63afa1c13a0a5e5", "60");
when(this.customerService.handleUpdateCustomerProduct(any()))
.thenReturn(buildDummyNotification(messageId, "SUCCESS"));
mockMvc.perform(post("/cpdupdate")
.contentType(MediaType.APPLICATION_XML)
.content(objectToString(validCustomer)))
.andExpect(status().isOk()); // Fails Here as it gets 400 in return
}
// Customer Class Generated from Provided XSD on maven build
private static Customer createValidCustomer(String internalProductId, int customerId) {
Customer customer = new Customer();
customer.setCustomerId(customerId);
Customer.InternalProducts products = new Customer.InternalProducts();
products.getProductIds().add(internalProductId);
customer.setInternalProducts(products);
return customer;
}
private Notification buildDummyNotification(String messageId, String message) {
return Notification.builder()
.messageId(messageId)
.message(message)
.build();
}
private static String objectToString(Object element) {
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
JAXBContext context = JAXBContext.newInstance(element.getClass());
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(element, outputStream);
return outputStream.toString("UTF-8");
} catch (JAXBException | IOException ex) {
log.error(ex.getMessage(), ex);
return "";
}
}
}
错误消息包含JSON parse error: Can not deserialize instance of java.util.ArrayList out of VALUE_STRING token
。因此,我尝试将ObjectMapper
和Import
的配置添加到测试中。
@Configuration
public class TestObjectMapperConfig {
@Bean
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
return objectMapper;
}
}
但是我仍然会收到错误消息。
我在这里想念什么?
完整错误消息
Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Can not deserialize instance of java.util.ArrayList out of VALUE_STRING token; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.util.ArrayList out of VALUE_STRING token
at [Source: java.io.PushbackInputStream@53311681; line: 4, column: 49] (through reference chain: com.clps.Customer["internalProducts"]->com.clps.Customer$InternalProducts["productId"])]
MockHttpServletRequest:
HTTP Method = POST
Request URI = /cpdupdate
Parameters = {}
Headers = {Content-Type=[application/xml]}
Handler:
Type = com.pt.controllers.InternalCustomerController
Method = public com.pt.models.Notification com.pt.controllers.InternalCustomerController.updateCustomerProduct(com.clps.Customer)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = org.springframework.http.converter.HttpMessageNotReadableException
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 400
Error message = null
Headers = {}
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
java.lang.AssertionError: Status
Expected :200
Actual :400