使用 Mockito 测试可能抛出异常的 POST 服务的正确方法?

Proper way to test POST service which may throw exception using Mockito?

我有一个用 Java (Spring Boot) 编写的简单 REST 服务。这个想法是允许用户在该实体不存在时添加新实体。如果确实存在,我将抛出异常。

代码如下:

    public ResponseEntity<String> addReadings(int clientId, int year, int month, double additionalConsumption) throws NoSuchMessageException, IllegalModificationException{     
    
    Optional<Client> clientOptional = clientService.findByClientId(clientId);

    if (clientOptional.isEmpty()) {
        return ResponseEntity.status(HttpStatus.NO_CONTENT)
                             .header("message", messageSource.getMessage("client.error1", null, new Locale("EN")))
                             .build(); 
    }
    
    Optional<Reading> reading = readingService.findByClientAndYearAndMonth(clientOptional.get(), year, month);
    
    if (reading.isPresent()) throw new IllegalModificationException(messageSource.getMessage("consumption.error2", null, new Locale("EN")));
            
    readingService.save(Reading.builder()
                                .client(clientOptional.get())
                                .year(year)
                                .month(month)
                                .consumption(additionalConsumption)
                                .build());
    

    return ResponseEntity
            .status(HttpStatus.OK)
            .body(messageSource.getMessage("sucess", null, new Locale("EN")));
}

问题是如何在Spring框架中使用Mockito以最简单和最干净的方式测试抛出异常?

模拟 readingService 以便 readingService.findByClientAndYearAndMonth returns 一个代表某个值的 Optional,即 reading.isPresent()true.

类似于:

Client client = ...
ReadingServiceClass readingService = Mockito.mock(ReadingServiceClass.class);
Mockito
  .when(readingService.findByClientAndYearAndMonth(client, 10, 2020))
  .thenReturn(Optional.of(new Reading(...)));
// ... inject readingService into objectToTest 
try {
  objectToTest.addReadings(1, 2020, 10, 1.0d);
  Assert.fail();
}  (catch IllegalModificationException e) {
  // ... assert details of exception
}