No se pudo obtener la entidad de respuesta de una API con MockMvc.
Tengo un problema cuando intento ejecutar la clase de prueba unitaria del controlador. Siempre obtengo un cuerpo vacío en la respuesta y no logro encontrar el motivo. Adjunto aquí el código. Quizá alguien con una visión externa pueda ver la razón.
El controlador:
@ResponseBody
@PostMapping(path = "/upload", consumes = { MediaType.MULTIPART_FORM_DATA_VALUE }, produces = { MediaType.APPLICATION_JSON_VALUE })
public ResponseEntity<object> uploadFile(@RequestParam("file") MultipartFile multipartFileData, @RequestParam(name="jobId", required = false) String jobId) {
JobStatus result;
try {
result = this.fileService.uploadFileChunk(multipartFileData, 1, 1, jobId);
}catch (ExecutionException|InterruptedException|IOException ex){
Thread.currentThread().interrupt();
return new ResponseEntity<>(ex,HttpStatus.INTERNAL_SERVER_ERROR);
}
return new ResponseEntity<>(result,HttpStatus.OK);
}
La clase de prueba unitaria:
@RunWith(SpringRunner.class)
@SpringBootTest(classes= FileUploadServiceRestController.class)
public class FileUploadServiceControllerTest {
private MockMvc mockMvc;
@Autowired
private WebApplicationContext context;
@MockBean
private FileUploadServiceImpl fileService;
@Before
public void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
}
@Test
public void testUploadFile()
throws Exception {
MockMultipartFile file = new MockMultipartFile(
"file",
"hello.txt",
MediaType.TEXT_PLAIN_VALUE,
"Hello, World!".getBytes()
);
JobStatus job = new JobStatus("uuid", ConstantUtil.JOB_STARTED);
when(fileService.uploadFileChunk(Mockito.any(MultipartFile.class),Mockito.eq(1),Mockito.eq(1),Mockito.isNull())).thenReturn(job);
mockMvc.perform(MockMvcRequestBuilders.multipart("/file/upload").file(file))
.andDo(MockMvcResultHandlers.print())
.andExpect(status().isOk());
}
}
El objeto que se transferirá:
public class JobStatus implements Serializable {
private static final long serialVersionUID = -4405865740177389860L;
private String jobId;
private String status;
public JobStatus() {
}
public JobStatus(String jobId, String status) {
this.jobId = jobId;
this.status = status;
}
public String getJobId() {
return jobId;
}
public void setJobId(String jobId) {
this.jobId = jobId;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}
Para información, este controlador funciona bien cuando lo llamo desde el cliente. Puedo ver que el mock se devuelve correctamente cuando pongo un punto de interrupción al final del controlador, pero el cuerpo de la respuesta sigue vacío.
Añado aquí el resultado de la impresión por si pudiera ayudar:
MockHttpServletRequest:
HTTP Method = POST
Request URI = /file/upload
Parameters = {}
Headers = [Content-Type:"multipart/form-data"]
Body = <no character="" encoding="" set="">
Session Attrs = {}
Handler:
Type = org.iso.fileservice.controller.FileUploadServiceRestController
Method = org.iso.fileservice.controller.FileUploadServiceRestController#uploadFile(MultipartFile, String)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = org.springframework.http.converter.HttpMessageNotWritableException
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 500
Error message = null
Headers = []
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
Gracias, Mathieu
davy.ai
El problema parece estar en que el cuerpo de respuesta está vacío en la clase de prueba de unidad del controlador. Aquí hay algunas cosas que puede intentar para resolver el problema:
Verifique si el objeto simulado se devuelve correctamente por la clase FileUploadServiceImpl.
Verifique si el objeto JobStatus se está serializando correctamente en el cuerpo de respuesta. Puede intentar agregar un punto de interrupción en el punto donde se crea el objeto de respuesta y verificar si los valores se están configurando correctamente.
También puede intentar cambiar el tipo de retorno del método uploadFile a String (en lugar de ResponseEntity
Pruebe estos pasos y vea cuál resuelve el problema. ¡Buena suerte!