异常描述
启动java测试类报了以下错误:
我的测试类代码如下:
@SpringBootTest
@RunWith(SpringRunner.class)
public class SimulatorApplicationTests {
@Autowired
ApplicationContext applicationContext;
@Autowired
DataSourceProperties dataSourceProperties;
@Test
public void testDataSource() throws Exception {
// 获取配置的数据源
DataSource dataSource = applicationContext.getBean(DataSource.class);
// 查看配置数据源信息
System.out.println(dataSource);
System.out.println(dataSource.getClass().getName());
System.out.println(dataSourceProperties);
}
}
排查原因
通过查看错误日志我们可以发现 SpringJUnit4ClassRunner 第137行出现了错误如下所示:
接着我们进入这个类然后在第137行打上一个断点如下所示:
第137代码调用了父类构造器出现了异常,这里我们点进去看以下父类构造器的相关代码如下所示:
我们发现这块仍然调用了其当前类的父类构造器我们再次点进去发现其构造器有两个方法如下所示:
我们重点查看第二步骤 validate() 方法我们点进去如下所示:
可以清晰看到collectInitializationErrors(errors) 这块代码是收集异常对象并将可能出现的异常对象添加至集合对象 errors 中,我们继续点进去这个方法中如下所示:
然后断点走到下一步如下所示:
然后在点击下一步如下所示:
然后点击下一步我们发现当前方法跳到另一个子类方法中,然后子类的方法调用了父类的方法如下所示:
我们继续debug向下走如下所示:
然后继续执行到 validateFields(errors) 发现出现了异常。
我们点进去回退一步在这个方法内部进行debug如下所示:
所以具体定位到是满足了 computeTestMethods().size() == 0 这个判断条件才在集合中添加了异常对象,所以我们点进这个方法一探究竟如下所示:
getTestClass() 这个返回的是TestClass对象我们重点跟踪 getAnnotatedMethods 这个方法的参数是 org.junit.Test 注解的class文件,我们再次点进去查看如下所示:
点进 getAnnotatedMembers 这个方法中如下所示:
返回的集合长度为0即满足了前面的computeTestMethods().size() == 0 方法所以导致后面程序就抛异常 ,让我回过头再来看一下validateTestMethods(errors)
这个方法。
我们点进去这个方法如下所示;
我们点进去可以看到 annotation 的值为org.junit.Test
。
我们在点进去getAnnotatedMethods 这个方法如下:
继续点进 getAnnotatedMembers这个方法如下所示:
我们发现程序会尝试去map中获取 key为interface org.junit.Test
的value值,但是map中现在只有 interface org.junit.jupiter.api.Test
解决方案
我们发现是获取不到org.junit.Test
这个注解类 导致的异常,然而debug程序发现实际获得的确是 org.junit.jupiter.api.Test
这个注解。所以一切的一切是我们导错包,程序在重新导入正确的包即可。
总结
- 程序运行时会验证是否可以从 TestClass 的 methodsForAnnotations 这个个map是否可以取出 key 为
org.junit.Test
对应的value值。 - 无论是否能从map中取到值都会返回集合对象需要注意的是获取不到会返回一个empty的List集合对象(也就是长度为0的集合对象)
- 然后判断集合长度为0就抛出 No runnable methods 的异常。