如何为Try-Catch块编写JUnit测试以覆盖异常分支?
JUnit测试覆盖Catch块问题排查与修正
我正在为一段包含Try-Catch的数据库健康检查代码编写JUnit测试,已经实现了Try块的覆盖率,但始终无法覆盖Catch块。
待测试代码
public boolean testDb() { boolean dbHealth = true; try { Session session = sessionFactory.getCurrentSession(); SQLQuery sqlQuery = session.createSQLQuery("SELECT empId from employee"); sqlQuery.executeUpdate(); } catch (Exception e) { dbHealth = false; LOG.error(e); } return dbHealth; }
现有测试代码(未生效)
@Test public void testDb_throwException() { SessionFactory sessionFactory = mock(SessionFactory.class); Session session= mock(Session.class); Query query = mock(Query.class); when(sessionFactory.getCurrentSession()).thenReturn(session); when(sessionFactory.openSession()).thenReturn(session); when(mockSession.createSQLQuery(Mockito.anyString())).thenReturn(query); when(query.executeUpdate()).thenThrow(new RuntimeException("sql exception")); boolean res= baseDaoImpl.testDatabaseHealth(); Assert.assertTrue(res); }
问题排查与修正
现有测试存在三个关键问题导致无法进入Catch块:
- 引用未定义的
mockSession对象,应使用已mock的session变量 - 断言逻辑错误:Catch块返回
false,但测试中误用Assert.assertTrue(res) - 未将mock的
sessionFactory注入到baseDaoImpl实例,导致测试实际使用非mock对象
修正后的测试代码
@Test public void testDb_throwException() { // 创建mock对象 SessionFactory sessionFactory = mock(SessionFactory.class); Session session = mock(Session.class); SQLQuery sqlQuery = mock(SQLQuery.class); // 匹配原代码的SQLQuery类型 // 将mock注入目标对象(根据实际注入方式调整,这里假设用setter) baseDaoImpl.setSessionFactory(sessionFactory); // 定义mock行为 when(sessionFactory.getCurrentSession()).thenReturn(session); when(session.createSQLQuery(Mockito.anyString())).thenReturn(sqlQuery); when(sqlQuery.executeUpdate()).thenThrow(new RuntimeException("sql exception")); // 执行测试并断言 boolean res = baseDaoImpl.testDb(); Assert.assertFalse(res); }
额外注意事项
- 保持mock对象类型与原代码一致:原方法使用
SQLQuery,不要用父类Query,否则类型不匹配会导致mock失效 - 确认注入方式:如果
baseDaoImpl的sessionFactory是构造函数注入,需在实例化时传入mock对象;字段注入可使用@InjectMocks注解自动注入 - 异常选择:抛出
RuntimeException即可触发Catch块,也可根据需求抛出更具体的异常如SQLException
内容的提问来源于stack exchange,提问作者Coder
相关产品推荐
相关产品推荐

