【问题标题】:Adding Code Coverage for catch block in Spring boot在 Spring Boot 中为 catch 块添加代码覆盖率
【发布时间】:2019-11-07 13:57:08
【问题描述】:

使用2.1.6.RELEASE

这是我的带有 repo.save 方法的 serviceImpl 类,如果 db 字段重复,我们会捕获异常并在响应中返回

@Service
public class CoreVoucherServiceImpl implements CoreVoucherService {

    @Override
    @Transactional(propagation = REQUIRED)
    public VoucherDTO createVoucher(VoucherDTO voucherDTO) {
        ... /* transforming DTO to Entity */
        try {
            voucherRepository.save(voucher);
        } catch (Exception e) {
            if (e.getCause() instanceof ConstraintViolationException) {
                throw new MyException(FIELD_NOT_UNIQUE, "title");
            }
            UB_LOGGER.debug("Error in create voucher", e);
            throw e;
        }
        voucherDTO.setId(voucher.getId());
        return voucherDTO;
    }
}

我无法为 catch 块添加代码覆盖率。我的测试课是

@SpringBootTest
@RunWith(SpringRunner.class)
public class CoreVoucherServiceTest {

    @Autowired
    private CoreVoucherService coreVoucherService;

    @MockBean
    private VoucherRepository voucherRepository;

    @Test
    // @Test(expected = MyException.class)
    public void createVoucherTest() {
        VoucherDTO dto = prepareCreateVoucher();
        when(voucherRepository.save(any())).thenThrow(Exception.class);
        coreVoucherService.createVoucher(dto);
    }
}

通过上述方式我得到以下错误

org.mockito.exceptions.base.MockitoException: 
Checked exception is invalid for this method!
Invalid: java.lang.Exception

如何抛出 getCauseConstraintViolationException 的异常,以便测试涵盖所有行

【问题讨论】:

  • 你试过抛出不同类型的异常吗?
  • 是的,但这不包括MyException线
  • 如果是 ConstraintViolationException 类型,是的,如果你抛出异常,不是。您是否阅读了您要测试的代码?仅当您的 try 块抛出 ConstraintViolationException 时才会抛出 MyException
  • @Stultuske 如何抛出 getCauseConstraintViolationException 的异常,因此所有行都包含在测试中

标签: java spring-boot junit code-coverage


【解决方案1】:

您必须在 catch 块中测试两个用例:

当异常原因为ConstraintViolationException

.thenThrow(new RuntimeException(new ConstraintViolationException("Field not Unique", null, "title")));

当异常原因不是ConstraintViolationException

.thenThrow(new RuntimeException("oops"));

对于这种情况,@ExpectedException 将是 RuntimeException

【讨论】:

  • 谢谢,它成功了。 ConstraintViolationException 来自org.hibernate.exception。因此使用.thenThrow(new RuntimeException(new ConstraintViolationException("Field not Unique", null, "title")))
【解决方案2】:

你应该抛出ConstraintViolationException,因为save方法根据它的方法定义save不会抛出任何检查异常

when(voucherRepository.save(any()))
      .thenThrow(.ConstraintViolationException.class); 

【讨论】:

  • 抛出RuntimeException 不覆盖MyException 行我也必须设置@Test(expected=RuntimeException.class)
  • ConstraintViolationException你应该很好@KedarJavalkar
  • 如何抛出 getCauseConstraintViolationException 的异常,以便所有行都包含在测试中
  • 你试过我的代码了吗?如果您尝试我的代码,您的异常块中的代码将被覆盖。 @KedarJavalkar
  • 是的,我试过了。我需要一个异常,其原因是ConstraintViolationException
【解决方案3】:

您还可以在 Junit 中使用 @Rule 和 ExpectedException 测试异常。

@SpringBootTest
@RunWith(SpringRunner.class)
public class CoreVoucherServiceTest {

    @Autowired
    private CoreVoucherService coreVoucherService;

    @MockBean
    private VoucherRepository voucherRepository;

    @Rule
    public ExpectedException exceptionRule = ExpectedException.none();

    @Test
    // @Test(expected = MyException.class)
    public void createVoucherTest() {
        exceptionRule.expect(Exception.class); // Better if you specify specific Exception class that is going to be thrown.
        VoucherDTO dto = prepareCreateVoucher();
        when(voucherRepository.save(any())).thenThrow(Exception.class);
        coreVoucherService.createVoucher(dto);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-09
    • 1970-01-01
    • 2018-09-30
    • 2011-06-24
    • 1970-01-01
    • 1970-01-01
    • 2021-04-21
    • 2017-11-29
    相关资源
    最近更新 更多