1

У меня есть приложение Spring Boot и вы хотите, чтобы мои контроллеры REST были интегрированы с помощью теста интеграции. Вот мой контроллер:Тестирование Spring Boot: исключение в контроллере REST

@RestController 
@RequestMapping("/tools/port-scan") 
public class PortScanController { 
    private final PortScanService service; 

    public PortScanController(final PortScanService portScanService) { 
     service = portScanService; 
    } 

    @GetMapping("") 
    public final PortScanInfo getInfo(
      @RequestParam("address") final String address, 
      @RequestParam(name = "port") final int port) 
      throws InetAddressException, IOException { 
     return service.scanPort(address, port); 
    } 
} 

В одном из тестов, которые я хочу, чтобы проверить, что конечная точка генерирует исключение, в некоторых обстоятельствах. Вот мой тестовый класс:

@RunWith(SpringRunner.class) 
@WebMvcTest(PortScanController.class) 
public class PortScanControllerIT { 
    @Autowired 
    private MockMvc mvc; 

    private static final String PORT_SCAN_URL = "/tools/port-scan"; 

    @Test 
    public void testLocalAddress() throws Exception { 
     mvc.perform(get(PORT_SCAN_URL).param("address", "192.168.1.100").param("port", "53")).andExpect(status().isInternalServerError()); 
    } 
} 

Каков наилучший способ сделать это? Текущая реализация не обрабатывает InetAddressException которого выкинули из PortScanController.getInfo(), и когда я начинаю тест, я получаю и ошибка:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is com.handytools.webapi.exceptions.InetAddressException: Site local IP is not supported 

Это не представляется возможным указать ожидаемое исключение в @Test аннотацию, так как оригинал InetAddressException является завернутый с помощью NestedServletException.

ответ

2

Можно определить обработчик исключений

@ExceptionHandler(InetAddressException.class) 
@ResponseStatus(HttpStatus.BAD_REQUEST) 
@ResponseBody 
public Response handledInvalidAddressException(InetAddressException e) 
{ 
    log e 
    return getValidationErrorResponse(e); 
} 

, а затем в тесте вы могли бы сделать

mvc.perform(get(PORT_SCAN_URL) 
    .param("address", "192.168.1.100") 
    .param("port", "53")) 
    .andExpect(status().isBadRequest()) 
    .andExpect(jsonPath("$.response").exists()) 
    .andExpect(jsonPath("$.response.code", is(400))) 
    .andExpect(jsonPath("$.response.errors[0].message", is("Site local IP is not supported"))); 
+0

Спасибо, Борис. Как я могу это сделать, учитывая, что у меня есть автоконфигурированный экземпляр MockMvc? – DavyJohnes

+0

Я имел в виду обработчик исключений для вашего приложения, а не ваш тест. Чтобы ваше приложение объявляло '@ExceptionHandler (InetAddressException.class)', а затем отвечает кодом состояния 400 или 503 с сообщением об ошибке, тогда ваш тест ищет ответ ожидаемого кода состояния и ожидаемого сообщения об ошибке. – borowis

+0

, потому что то, что вы получаете, действительно является ошибкой проверки, поэтому мне кажется, что код 400 вместе с сообщением об ошибке мне подходит – borowis

4

Для того, чтобы проверить, обернутый исключение (т.е. InetAddressException), вы можете создать JUnit Правило, используя класс ExpectedException, а затем установите expectMessage() (получено от NestedServletExceptiongetMessage(), которое содержит фактическую причину), для получения точного значения вы можете указать приведенный ниже код:

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

@Test 
public void testLocalAddress() { 

    //Set the message exactly as returned by NestedServletException 
    inetAddressExceptionRule.expectMessage("Request processing failed; nested exception is com.handytools.webapi.exceptions.InetAddressException: Site local IP is not supported"); 

    //or you can check below for actual cause 
    inetAddressExceptionRule.expectCause(org.hamcrest.Matchers.any(InetAddressException.class)) 

    //code for throwing InetAddressException here (wrapped by Spring's NestedServletException) 
} 

Вы можете передать ExpectedException API здесь:

http://junit.org/junit4/javadoc/4.12/org/junit/rules/ExpectedException.html

+0

К сожалению, это не сработает. Как я упоминал в своем вопросе, исходное исключение обернуто с помощью NestedServletException. – DavyJohnes

+0

Уже сделано. Это не работает. jUnit не обрабатывает это исключение. – DavyJohnes

+0

Посмотрите мой код, чтобы создать правило ExpectedException – developer

6

пакет Spring загрузки Тест поставляется с AssertJ, который имеет очень удобный способ проверки брошенные исключения.

Чтобы проверить причину:

@Test 
public void shouldThrowException() { 
    assertThatThrownBy(() -> methodThrowingException()).hasCause(InetAddressException .class); 
} 

Есть также несколько методов, которые могут быть заинтересованы в Я предлагаю иметь взгляд в docs..

Смежные вопросы