问题描述
后台添加新菜单后,mvn test
运行单元测试,WebAppMenuControllerTest.java
报了如下错误。
org.springframework.web.util.NestedServletException: Request processing failed;
nested exception is org.springframework.http.converter.HttpMessageNotWritableException:
Could not write JSON document:
Direct self-reference leading to cycle
(through reference chain: java.util.ArrayList[98]
->com.mengyunzhi.measurement.entity.WebAppMenu["parentWebAppMenu"]);
起初,还是怀着对控制台错误信息惧怕的原理,自己倒腾了半天也没有什么结果。
翻译这行错误:不能写入JSON
文档,直接引用导致循环。
去看抛出错误的测试代码:
public class WebAppMenuControllerTest extends ControllerTest {
@Test
public void getAll() throws Exception {
MvcResult mvcResult = this.mockMvc.perform(get("/WebAppMenu/")
.header("x-auth-token", xAuthToken)
.contentType(MediaType.APPLICATION_JSON_UTF8))
.andDo(document("WebAppMenu", preprocessResponse(prettyPrint())))
.andExpect(status().isOk())
.andReturn();
String content = mvcResult.getResponse().getContentAsString();
JSONArray jsonArray = JSONArray.fromObject(content);
assertThat(jsonArray.size()).isGreaterThan(8);
return;
}
}
测试映射GetMapping("/WebAppMenu/")
出现了错误,找到这个映射对应的方法:
@Api(tags = "WebAppMenu 前台菜单", description = "前台菜单 用于前台注册路由及显示左侧菜单")
@RequestMapping("/WebAppMenu")
@RestController
public class WebAppMenuController {
// 前台菜单
@Autowired
private WebAppMenuService webAppMenuService;
@ApiOperation(value = "/ 获取所有菜单列表", notes = "获取所有的前台菜单", nickname = "WebAppMenu")
@GetMapping("/")
public List getAll() {
return webAppMenuService.getAll();
}
}
该方法调用了我们的M
层WebAppMenuService
中的getAll
方法,我们去查看该方法。
@Service
public class WebAppMenuServiceImpl implements WebAppMenuService {
@Autowired
private WebAppMenuRepository webAppMenuRepository;
@Override
public List getAll() {
List list = new ArrayList();
// 按权重进行排序,权重越小越靠前
list = (List)webAppMenuRepository.findAll(new Sort("weight"));
return list;
}
}
这里返回了一个List
,在此打一个断点,然后debug
我们刚刚的测试文件。
我们展开看一下返回的list
有没有问题。
展开,发现第98条记录(检定能力覆盖率统计)栈溢出,找到初始化菜单的代码,找到生成检定能力覆盖率统计菜单的代码。
logger.info("检定能力覆盖率统计");
WebAppMenu checkAbilityCoverageRate = new WebAppMenu();
checkAbilityCoverageRate.setName("检定能力覆盖率统计");
checkAbilityCoverageRate.setDescription("强检器具统计管理-检定能力覆盖率统计");
checkAbilityCoverageRate.setRouteName("coverageRate");
checkAbilityCoverageRate.setParentWebAppMenu(checkAbilityCoverageRate);
checkAbilityCoverageRate.setParentRouteWebAppMenu(checkAbilityCoverageRate);
checkAbilityCoverageRate.setTemplateUrl("views/forceInstrumentStatistics/coverageRate/index.html");
webAppMenus.add(checkAbilityCoverageRate);
这里,误将该菜单的父菜单设置为自己,所以获取数据时就会无限循环,也就是报错信息中给我们的提示:直接引用导致循环。
修正代码,再次运行单元测试。
总结
遇到cycle
关键字,可能就是对象之间的关系设置错误,导致一直循环。