JUnit测试报错:无法将VALUE_STRING/VALUE_TRUE反序列化为ArrayList
解决Jackson反序列化List时的类型不匹配问题
看起来你遇到的核心问题是Mock返回的JSON字符串格式和被测方法期望的类型完全不匹配,咱们一步步拆解解决:
报错原因分析
- 第一个错误
Unrecognized token 'test':你返回的"test"根本不是合法的JSON格式,Jackson完全无法解析它。 - 第二个错误
Cannot deserialize instance of java.util.ArrayList out of VALUE_TRUE token:你返回的"true"是合法JSON,但它是单个布尔值,而被测方法里要把它反序列化成List<Measurement>/List<Meal>/List<Training>——Jackson没法把单个布尔值转换成列表,自然会抛出类型不匹配的异常。
解决方案:返回合法的JSON数组格式
被测方法里的objectMapper.readValue(..., TypeReference<List<X>>())要求传入的JSON必须是JSON数组(用[]包裹的格式),所以你需要给每个getJSON调用返回对应类型的数组JSON:
方案1:返回空数组(适合测试空列表场景)
@Before public void setUp() throws Exception { activitiesService = new ActivitiesService(databaseControllerMock); when(databaseControllerMock.get(anyString(), any())).thenReturn(item); // 给三个字段都返回空数组JSON when(item.getJSON("measurements")).thenReturn("[]"); when(item.getJSON("meals")).thenReturn("[]"); when(item.getJSON("trainings")).thenReturn("[]"); }
方案2:返回带测试数据的JSON数组(适合测试非空列表场景)
如果需要测试有数据的情况,可以手动构造符合实体类字段的JSON数组,比如假设Measurement有id和value字段:
@Before public void setUp() throws Exception { activitiesService = new ActivitiesService(databaseControllerMock); when(databaseControllerMock.get(anyString(), any())).thenReturn(item); // 带示例数据的数组JSON when(item.getJSON("measurements")).thenReturn("[{\"id\":1, \"value\":120.5}]"); when(item.getJSON("meals")).thenReturn("[{\"name\":\"Lunch\", \"calories\":500}]"); when(item.getJSON("trainings")).thenReturn("[{\"name\":\"Swimming\", \"minutes\":45}]"); }
方案3:用ObjectMapper自动生成JSON(更灵活,避免手动写JSON出错)
如果实体类字段较多,手动写JSON容易出错,可以先创建测试用的实体列表,再用ObjectMapper转成JSON字符串:
@Before public void setUp() throws Exception { activitiesService = new ActivitiesService(databaseControllerMock); when(databaseControllerMock.get(anyString(), any())).thenReturn(item); ObjectMapper mapper = new ObjectMapper(); // 构造测试用的Measurement列表 List<Measurement> mockMeasurements = Arrays.asList(new Measurement(1, 120.5)); String measurementsJson = mapper.writeValueAsString(mockMeasurements); when(item.getJSON("measurements")).thenReturn(measurementsJson); // 同理处理meals和trainings List<Meal> mockMeals = Arrays.asList(new Meal("Lunch", 500)); when(item.getJSON("meals")).thenReturn(mapper.writeValueAsString(mockMeals)); List<Training> mockTrainings = Arrays.asList(new Training("Swimming", 45)); when(item.getJSON("trainings")).thenReturn(mapper.writeValueAsString(mockTrainings)); }
这样Mock返回的JSON就能被Jackson正确反序列化成对应的List对象,解决你的报错问题啦。
内容的提问来源于stack exchange,提问作者D.Zet
相关产品推荐
相关产品推荐

