如何为DAO层catch块编写JUnit测试用例以提升代码覆盖率?
问题:Spring Boot DAO层JUnit测试无法覆盖catch块
我正在为Spring Boot项目编写JUnit测试用例,目标是达到90%的代码覆盖率。现在想覆盖DAO层方法里的catch块,但写的测试用例没生效,覆盖不了。
DAO层代码
public class GeneratorRepository { @Value("${existingQuery}") private String existingQuery; @Autowired private NamedParameterJdbcTemplate namedParameterJdbcTemplate; @Autowired private BeanPropertyRowMapper<Generator> generatorRowMapper; public Generator findExisting(Request request) { Generator ut = new Generator(); try { SqlParameterSource namedParameters = new MapSqlParameterSource() .addValue("no", request.getId(), Types.VARCHAR) .addValue("trSu", request.getSu(), Types.VARCHAR) .addValue("sta", request.getSta(), Types.VARCHAR); ut = namedParameterJdbcTemplate.queryForObject(existingQuery, namedParameters, generatorRowMapper); } catch (EmptyResultDataAccessException e) { ut = null; } catch (Exception e) { throw e; } return ut; } }
现有测试用例(未覆盖catch块)
@Test public void findExistingException() { Request request = new Request("12365", "QW", "qw"); when(namedParameterJdbcTemplate.queryForObject(ArgumentMatchers.<String>any(), any(SqlParameterSource.class), eq(generatorRowMapper))).thenReturn(null); when(generatorRepo.findExisting(request)).thenThrow(new EmptyResultDataAccessException(1)); EmptyResultDataAccessException exception = assertThrows(EmptyResultDataAccessException.class, () -> generatorRepo.findExisting(request)); }
解决方案
原测试用例的问题
- 错误地直接mock了
generatorRepo.findExisting(request)的行为,相当于跳过方法内部逻辑直接抛异常,根本触发不了catch块 namedParameterJdbcTemplate.queryForObject查询无结果时会抛出EmptyResultDataAccessException,而非返回null,原mock的返回值不符合实际逻辑
修正后的测试用例
测试EmptyResultDataAccessException catch块
@Test public void findExisting_WhenEmptyResult_ThenReturnNull() { Request request = new Request("12365", "QW", "qw"); // 让queryForObject抛出EmptyResultDataAccessException,触发第一个catch块 when(namedParameterJdbcTemplate.queryForObject( ArgumentMatchers.<String>any(), any(SqlParameterSource.class), eq(generatorRowMapper) )).thenThrow(new EmptyResultDataAccessException(1)); // 调用方法,验证返回值为null(catch块中设置的结果) Generator result = generatorRepo.findExisting(request); assertNull(result); }
测试通用Exception catch块
@Test public void findExisting_WhenGenericException_ThenThrowException() { Request request = new Request("12365", "QW", "qw"); RuntimeException testException = new RuntimeException("test error"); // 让queryForObject抛出通用Exception,触发第二个catch块 when(namedParameterJdbcTemplate.queryForObject( ArgumentMatchers.<String>any(), any(SqlParameterSource.class), eq(generatorRowMapper) )).thenThrow(testException); // 验证方法会重新抛出该异常 RuntimeException thrownException = assertThrows(RuntimeException.class, () -> generatorRepo.findExisting(request)); assertEquals(testException, thrownException); }
内容的提问来源于stack exchange,提问作者Rahul
相关产品推荐
相关产品推荐

