在 Spring 引导中为 catch 块添加代码覆盖率
Adding Code Coverage for catch block in Spring boot
使用2.1.6.RELEASE
这是我的 serviceImpl class 和 repo.save 方法,如果数据库字段重复,我们会捕获异常并 return 响应
@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 块添加代码覆盖率。我的测试 class 是
@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
如何抛出 getCause
为 ConstraintViolationException
的异常,以便所有行都包含在测试中
你应该抛出 ConstraintViolationException
,因为 save
方法根据它的方法定义不会抛出任何已检查的异常 save
when(voucherRepository.save(any()))
.thenThrow(.ConstraintViolationException.class);
您必须在 catch 块中测试两个用例:
异常原因为ConstraintViolationException
时
.thenThrow(new RuntimeException(new ConstraintViolationException("Field not Unique", null, "title")));
当异常原因不是ConstraintViolationException
时
.thenThrow(new RuntimeException("oops"));
对于这种情况 @ExpectedException
将是 RuntimeException
您还可以在 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);
}
}
使用2.1.6.RELEASE
这是我的 serviceImpl class 和 repo.save 方法,如果数据库字段重复,我们会捕获异常并 return 响应
@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 块添加代码覆盖率。我的测试 class 是
@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
如何抛出 getCause
为 ConstraintViolationException
的异常,以便所有行都包含在测试中
你应该抛出 ConstraintViolationException
,因为 save
方法根据它的方法定义不会抛出任何已检查的异常 save
when(voucherRepository.save(any()))
.thenThrow(.ConstraintViolationException.class);
您必须在 catch 块中测试两个用例:
异常原因为ConstraintViolationException
.thenThrow(new RuntimeException(new ConstraintViolationException("Field not Unique", null, "title")));
当异常原因不是ConstraintViolationException
.thenThrow(new RuntimeException("oops"));
对于这种情况 @ExpectedException
将是 RuntimeException
您还可以在 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);
}
}