Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/380.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring启动测试:当使用Jackson ObjectMapper将模型转换为JSON字符串时,UserControllerTest失败_Java_Validation_Objectmapper_Spring Boot Test_Mockmvc - Fatal编程技术网

Java Spring启动测试:当使用Jackson ObjectMapper将模型转换为JSON字符串时,UserControllerTest失败

Java Spring启动测试:当使用Jackson ObjectMapper将模型转换为JSON字符串时,UserControllerTest失败,java,validation,objectmapper,spring-boot-test,mockmvc,Java,Validation,Objectmapper,Spring Boot Test,Mockmvc,我正在Spring Boot中测试一个@RestContoller,它有一个@PostMapping方法,该方法@RequestBody使用@Valid注释进行验证。为了测试它,我使用了MockMvc,为了填充请求正文内容,我使用了jacksonobjectmapper;但是,当模型通过时,测试失败: MockHttpServletRequest: HTTP Method = POST Request URI = /api/user/register Par

我正在Spring Boot中测试一个
@RestContoller
,它有一个
@PostMapping
方法,该方法
@RequestBody
使用
@Valid
注释进行验证。为了测试它,我使用了
MockMvc
,为了填充请求正文内容,我使用了
jacksonobjectmapper
;但是,当模型通过时,测试失败:

MockHttpServletRequest:
      HTTP Method = POST
      Request URI = /api/user/register
       Parameters = {}
          Headers = [Content-Type:"application/json"]
             Body = <no character encoding set>
    Session Attrs = {}

Handler:
             Type = com.springboottutorial.todoapp.controller.UserController
           Method = public org.springframework.http.ResponseEntity<java.lang.String> com.springboottutorial.todoapp.controller.UserController.register(com.springboottutorial.todoapp.dao.model.User)

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
用户控制器:

@RestController
@RequestMapping("/api/user")
public class UserController {

    @Autowired
    UserService userService;

    @PostMapping("/register")
    public ResponseEntity<String> register(@RequestBody @Valid User user){
        userService.createUser(user);
        return ResponseEntity.ok().build();
    }
}
当我手动构建JSON字符串时,测试通过:

String json = "{\n" +
                "\t\"firstName\" : \"John\",\n" +
                "\t\"lastName\" : \"QPublic\",\n" +
                "\t\"password\" : \"123456789\",\n" +
                "\t\"createdAt\" : \"2016-11-09T11:44:44.797\",\n" +
                "\t\"updatedAt\" : \"2016-11-09T11:44:44.797\",\n" +
                "\t\"emailAddress\" : \"john.public@gmail.com\"\n" +
                "}";

        mockMvc.perform(MockMvcRequestBuilders.post("/api/user/register")
                .content(json)
                .contentType(MediaType.APPLICATION_JSON)
                )
                .andExpect(MockMvcResultMatchers.status().isOk());

这就是我实现rest控制器测试的方式。也许它能帮助你

我使用这个抽象类来封装关于JSON映射的常见测试功能

导入lombok.rows;
进口lombok.val;
导入org.springframework.beans.factory.annotation.Autowired;
导入org.springframework.http.MediaType;
导入org.springframework.http.converter.HttpMessageConverter;
导入org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
导入org.springframework.mock.http.MockHttpOutputMessage;
导入java.nio.charset.StandardCharset;
导入java.util.array;
导入静态org.junit.Assert.assertNotNull;
公共抽象类RestControllerTest{
private final MediaType contentType=new MediaType(MediaType.APPLICATION_JSON.getType(),
MediaType.APPLICATION_JSON.getSubtype(),
标准字符集(UTF_8);
私有HttpMessageConverter消息转换器;
受保护的MediaType getContentType(){
返回contentType;
}
@自动连线
void setConverters(HttpMessageConverter[]转换器){
messageConverter=Arrays.stream(转换器)
.filter(映射Jackson2HttpMessageConverter的hmc->hmc实例)
.findAny()
.orElse(空);
assertNotNull(“JSON消息转换器不能为null”,
信息转换器);
}
@鬼鬼祟祟
受保护的字符串toJson(对象数据){
val mockHttpOutputMessage=新建mockHttpOutputMessage();
messageConverter.write(
数据、MediaType.APPLICATION_JSON、mockHttpOutputMessage);
返回mockHttpOutputMessage.getBodyAsString();
}
}
你可以像这样在你的测试课上使用它

@WebMvcTest(UserController.class)
@自动配置emockmvc(addFilters=false)
公共类UserControllerTest扩展了RestControllerTest{
@自动连线
MockMvc-MockMvc;
@试验
当requestValid\u thenReturnStatusOk()引发异常时公共无效{
用户用户=新用户(“John”、“QPublic”、“John”。public@gmail.com",
“123456789”,LocalDateTime.now(),LocalDateTime.now());
mockMvc.perform(MockMvcRequestBuilders.post(“/api/user/register”)
.content(toJson(用户))
.contentType(MediaType.APPLICATION_JSON)
)
.andExpect(MockMvcResultMatchers.status().isOk());
}
}

我希望它适合您

正如chrylis在评论中提到的,问题是由于Java8日期与时间API和Jackson序列化冲突造成的。默认情况下,
ObjectMapper
不理解
LocalDateTime
数据类型,因此我需要将
com.fasterxml.jackson.datatype:jackson-datatype-jsr310
依赖项添加到我的maven中,这是一个数据类型模块,可以让jackson识别Java 8日期和时间API数据类型。A和A帮助我找出了我的问题所在。

如果
LocalDateTime
不是问题,我认为我们应该在用户类中实现
equals

Spring不一定为您提供“普通”的ObjectMapper实例。通过让Spring将ObjectMapper实例注入到测试中,而不是使用默认构造函数创建ObjectMapper,只要单元测试的Spring概要文件设置正确,您将获得与实际运行时环境匹配的实例

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc(addFilters = false)
public class UserControllerTest {

    @Autowired
    MockMvc mockMvc;

    @Autowired
    ObjectMapper objectMapper;

    @Test
    public void whenRequestValid_thenReturnStatusOk() throws Exception{
        User user = new User("John", "QPublic", "john.public@gmail.com",
                "123456789", LocalDateTime.now(), LocalDateTime.now());      
        mockMvc.perform(MockMvcRequestBuilders.post("/api/user/register")
                .content(objectMapper.writeValueAsString(user))
                .contentType(MediaType.APPLICATION_JSON)
                )
                .andExpect(MockMvcResultMatchers.status().isOk());
    }
}

您是否运行应用程序来检查端点是否正在使用Postman或其他类似工具?。请在回答中包含您的
pom.xml
您是否尝试打印出
writeValueAsString
返回的字符串以验证它?(我非常怀疑你得到的是“时间戳”格式,除了用户日历之外,不要使用
Local*
;而是使用
Instant
。@EduardoEljaiek是的,当我使用邮递员工具时,它运行正常。@chrylis感谢你的建议!LocalDateTime在映射到JSON字符串时解析为天、月、年,因此出现冲突。我使LocalDateTime为空,这一次成功了。我正试图提出一个解决方案,并公布答案。
String json = "{\n" +
                "\t\"firstName\" : \"John\",\n" +
                "\t\"lastName\" : \"QPublic\",\n" +
                "\t\"password\" : \"123456789\",\n" +
                "\t\"createdAt\" : \"2016-11-09T11:44:44.797\",\n" +
                "\t\"updatedAt\" : \"2016-11-09T11:44:44.797\",\n" +
                "\t\"emailAddress\" : \"john.public@gmail.com\"\n" +
                "}";

        mockMvc.perform(MockMvcRequestBuilders.post("/api/user/register")
                .content(json)
                .contentType(MediaType.APPLICATION_JSON)
                )
                .andExpect(MockMvcResultMatchers.status().isOk());
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc(addFilters = false)
public class UserControllerTest {

    @Autowired
    MockMvc mockMvc;

    @Autowired
    ObjectMapper objectMapper;

    @Test
    public void whenRequestValid_thenReturnStatusOk() throws Exception{
        User user = new User("John", "QPublic", "john.public@gmail.com",
                "123456789", LocalDateTime.now(), LocalDateTime.now());      
        mockMvc.perform(MockMvcRequestBuilders.post("/api/user/register")
                .content(objectMapper.writeValueAsString(user))
                .contentType(MediaType.APPLICATION_JSON)
                )
                .andExpect(MockMvcResultMatchers.status().isOk());
    }
}