如何使用MockMvc给MULTIPART_FORM_DATA类型Controller传PaymentOrderDto
解决方法
首先明确:你的Controller中PaymentOrderDto未标注@RequestPart注解,属于表单参数自动绑定场景,Spring会自动将同名表单参数映射到Dto对应属性,按以下步骤构造请求即可:
完整实现代码
import org.springframework.http.MediaType; import org.springframework.mock.web.MockMultipartFile; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import java.math.BigDecimal; import java.nio.file.Files; import java.nio.file.Paths; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; // 1. 构造并赋值你的PaymentOrderDto对象 PaymentOrderDto paymentOrderDto = new PaymentOrderDto(); paymentOrderDto.setMid("m1"); paymentOrderDto.setOrderAmount(new BigDecimal("99.9")); // 按需添加其他属性赋值 String requiredContactId = "contact_12345"; // 可选:构造待上传的支付凭证文件,不需要上传可跳过本段 MockMultipartFile receiptFile = new MockMultipartFile( "paymentReceiptFile", // 必须和Controller中@RequestPart注解的参数名一致 "20240520_receipt.png", MediaType.IMAGE_PNG_VALUE, Files.readAllBytes(Paths.get("本地文件路径")) // 也可以直接传自定义字节数组 ); // 2. 构造multipart请求并执行测试 mockMvc.perform(MockMvcRequestBuilders.multipart("/你的接口请求路径") .contentType(MediaType.MULTIPART_FORM_DATA_VALUE) // 添加必填参数contactId .param("contactId", requiredContactId) // 添加PaymentOrderDto的所有属性,参数名必须和Dto字段名完全一致 .param("mid", paymentOrderDto.getMid()) .param("orderAmount", paymentOrderDto.getOrderAmount().toString()) // 其他Dto属性按上述格式逐个添加 // 有上传文件需求就加下面这行,没有就省略 .file(receiptFile) ) // 以下为断言示例,按需调整 .andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_JSON));
简化方案(Dto属性较多时使用)
如果PaymentOrderDto属性较多,逐个写param太繁琐,可以借助ObjectMapper将Dto转成Map批量添加参数:
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.beans.factory.annotation.Autowired; import java.util.Map; // 注入ObjectMapper @Autowired private ObjectMapper objectMapper; // 赋值Dto的代码和上面一致,此处省略 // 将Dto转换为Map<String,String> Map<String, String> dtoParamMap = objectMapper.convertValue(paymentOrderDto, new TypeReference<Map<String, String>>() {}); // 构造请求时批量添加参数 MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.multipart("/你的接口请求路径") .contentType(MediaType.MULTIPART_FORM_DATA_VALUE) .param("contactId", requiredContactId); for (Map.Entry<String, String> entry : dtoParamMap.entrySet()) { if (entry.getValue() != null) { requestBuilder.param(entry.getKey(), entry.getValue()); } } // 有文件就加requestBuilder.file(receiptFile); mockMvc.perform(requestBuilder).andExpect(status().isOk());
注意事项
- 若Dto包含嵌套对象,参数名按
嵌套属性名.字段名格式编写即可,比如Dto中merchant属性的name字段,参数名为merchant.name,Spring会自动完成嵌套对象绑定 - 数字、日期等非字符串类型的属性直接转成字符串传入即可,Spring会自动完成类型转换
- 不需要上传文件时,无需构造
MockMultipartFile,省略.file()方法调用即可
内容的提问来源于stack exchange,提问作者HARPREET SINGH
相关产品推荐
相关产品推荐

