JUnit测试Querydsl查询方法时断言错误问题求助
嘿,我来帮你搞定这个断言错误的问题!从你给出的错误信息和代码来看,问题出在你对业务方法返回的Tuple结构理解错了,导致断言的时候拿错了对象。
问题根源分析
你的业务方法btnSearchClick里用了Projections.bean(Account.class, ...)把查询结果投影成一个Account对象,然后把这个对象放到了Tuple里。所以返回的List<Tuple>中,每个Tuple的第一个元素就是这个投影生成的Account实例。而你在测试里直接写account.get(0),拿到的是整个Account对象,不是你期望的sLocation字段值,这就导致了expected:<ON> but was:<com.spacestudy.model.Account@783f5f71>的错误。
另外还有两个隐藏的坑你得注意:
- 业务方法里的查询条件是
account.nInstId.eq(60),但你测试保存Account的时候没设置nInstId=60,这会导致查询结果为空,执行account.get(0)的时候直接抛IndexOutOfBoundsException。 - 测试用例里的
sAcctDesc、sInvestigatorName、sClientDeptId这些变量没初始化,传空值的话可能影响查询结果(另外看你业务方法参数是这四个,但查询逻辑里没加对应的过滤条件,后续如果要实现过滤记得补充)。
修复方案
1. 修正测试用例的断言逻辑
你需要从Tuple里取出投影的Account对象,再获取它的sLocation属性来断言:
@Test public void btnSearchClick() throws Exception { // 初始化测试参数 String sAcctDesc = "SRIRAM"; String sInvestigatorName = "Ram, Sri"; String sClientDeptId = "120010"; // 先保存关联实体,避免外键约束问题 Department dep = new Department(); dep.setsDeptName("Deans Office"); dep.setsClientDeptId("120010"); departmentRepo.save(dep); Investigator invest = new Investigator(); invest.setsInvestigatorName("Ram, Sri"); investigatorRepo.save(invest); AccountCPCMapping cpc = new AccountCPCMapping(); cpc.setsCCPCode("RT"); accountCPCMappingRepo.save(cpc); // 保存测试Account,必须设置nInstId匹配查询条件 Account acc = new Account(); acc.setsLocation("ON"); acc.setsAcctDesc("SRIRAM"); acc.setsClientAcctId("1124100"); acc.setInvestigator(invest); acc.setDepartment(dep); acc.setAccountCPC(cpc); acc.setnInstId(60); // 关键:匹配业务方法的where条件 accountRepo.save(acc); // 调用业务方法 List<Tuple> result = accountService.btnSearchClick("1124100", sAcctDesc, sInvestigatorName, sClientDeptId); // 从Tuple中取出Account对象,再获取sLocation断言 Account returnedAccount = result.get(0).get(0, Account.class); assertEquals(acc.getsLocation(), returnedAccount.getsLocation()); }
2. 优化业务方法(可选但推荐)
既然你已经用Projections.bean投影成了Account对象,其实没必要返回List<Tuple>,直接返回List<Account>会更清晰,也能避免后续的Tuple操作错误。修改业务方法:
public List<Account> btnSearchClick(String sClientAcctId, String sAcctDesc, String sInvestigatorName, String sClientDeptId) throws Exception { QAccount account = QAccount.account; QDepartment department = QDepartment.department; QAccountCPCMapping accountCPCMapping = QAccountCPCMapping.accountCPCMapping; QInvestigator investigator = QInvestigator.investigator; JPAQuery<Account> query = new JPAQuery<>(em); query.select(Projections.bean(Account.class, account.sClientAcctId, account.sAcctDesc, account.sLocation, Projections.bean(Department.class, department.sDeptName, department.sClientDeptId).as("department"), Projections.bean(Investigator.class, investigator.sInvestigatorName).as("investigator"), Projections.bean(AccountCPCMapping.class, accountCPCMapping.sCCPCode).as("accountCPC"))) .from(account) .innerJoin(account.department, department) .innerJoin(account.accountCPC, accountCPCMapping) .innerJoin(account.investigator, investigator) .where(account.nInstId.eq(60)); // 补充:如果要实现参数过滤,记得添加对应条件 // if (StringUtils.isNotEmpty(sClientAcctId)) { // query.where(account.sClientAcctId.eq(sClientAcctId)); // } // ...其他参数的过滤逻辑 return query.fetch(); }
修改后测试用例可以直接断言返回的Account对象属性:
List<Account> result = accountService.btnSearchClick("1124100", sAcctDesc, sInvestigatorName, sClientDeptId); assertEquals(acc.getsLocation(), result.get(0).getsLocation());
总结
核心问题就是你误把Tuple里的Account对象当成了sLocation字段,调整断言逻辑就能解决。同时别忘了设置匹配查询条件的nInstId,以及先保存关联的实体,这样测试才能正常运行。
内容的提问来源于stack exchange,提问作者SpringUser
相关产品推荐
相关产品推荐

