Java单元测试执行findByLoginAndPassword报InvalidUseOfMatchersException求助
异常触发原因
Mockito 的参数匹配器(如any()、anyString()、eq()等)有严格的使用范围限制:仅允许在 Mock 对象的打桩(when(...)、given(...))和调用校验(verify(...))场景中作为方法入参使用,禁止在普通业务方法的调用中作为参数传入。
你代码第71行直接调用业务方法userService.findByLoginAndPassword(any(), any())时用了any()匹配器,属于滥用场景:Mockito 会将调用时出现的2个any()记录到全局匹配器栈中,但此时并没有对应的 Mock 方法打桩/校验操作来消费这些匹配器,就会抛出匹配器数量不匹配的异常。
你其余测试方法中也存在userService.loadUserByUsername(any())、userDao.loadUserByLogin(any())这类错误写法,只是巧合没有触发报错,同样需要修复。
修复方案
所有普通方法调用的位置都传入真实的参数值即可,仅在打桩、verify 环节保留匹配器:
// 修复后的全部测试方法 @Test public void loadUserByUsernameTest(){ String testLogin = "test"; when(userDao.loadUserByLogin(any())).thenReturn(null); Assertions.assertThrows(UsernameNotFoundException.class, () -> userService.loadUserByUsername(testLogin)); when(userDao.loadUserByLogin(any())).thenReturn(getTestUser()); Assertions.assertEquals(userService.loadUserByUsername(testLogin).getAuthorities().size(), 1); } @Test public void findUserByLogin(){ String testLogin = "test"; when(userDao.loadUserByLogin(any())).thenReturn(getTestUser()); // 调用业务方法传入真实参数 Assertions.assertEquals(userService.findUserByLogin(testLogin).getLogin(), getTestUser().getLogin()); verify(userDao).loadUserByLogin(any()); } @Test public void findByLoginAndPassword(){ String testLogin = "test"; String testPwd = "123456"; when(userDao.loadUserByLogin(any())).thenReturn(getTestUser()); when(passwordEncoder.matches(any(), any())).thenReturn(true); // 业务方法调用传入真实参数,删除any() Assertions.assertEquals(userService.findByLoginAndPassword(testLogin, testPwd).getLogin(), getTestUser().getLogin()); verify(userDao).loadUserByLogin(any()); verify(passwordEncoder).matches(any(), any()); }
因为你已经对userDao、PasswordEncoder两个依赖做了全局打桩,不管调用业务方法时传入的具体值是什么,都会返回你预设的测试结果,不会影响测试逻辑的正确性。
内容的提问来源于stack exchange,提问作者Anton
相关产品推荐
相关产品推荐

