2016-11-27 5 views
4

Я использую Spring Boot 1.4.2 и Jersey (jax-rs) для создания контроллера REST. Я следил за документацией о том, как тестировать контроллеры REST (Testing the Spring MVC slice). Но мой тест возвращает 404, и я не могу понять, почему. Контроллер здесь упрощен, но проблема остается.Spring Boot 1.4.2 @WebMvcTest возвращает статус 404

Мой вопрос: как получить статус 200 при запуске теста?

HealthController.java

@Controller 
@Path("/health") 
public class HealthController { 
    @GET 
    @Produces(MediaType.APPLICATION_JSON) 
    public Health health() { 
     return Health.up().build(); 
    } 
} 

Запуск сервера и делать запрос дает мне эту

%> curl -i http://localhost:8080/health 
HTTP/1.1 200 
X-Application-Context: application 
Content-Type: application/json 
Content-Length: 21 
Date: Sun, 27 Nov 2016 15:22:30 GMT 

{ 
    "status" : "UP" 
}% 

HealthControllerTest.java

@RunWith(SpringRunner.class) 
@WebMvcTest(HealthController.class) 
public class HealthControllerTest { 

    @Autowired 
    private MockMvc mockMvc; 

    @Test 
    public void health() throws Exception { 
     mockMvc.perform(get("/health").accept(MediaType.APPLICATION_JSON)) 
       .andExpect(status().isOk()); // 200 expected 
    } 
} 

Это то, что я получаю при запуске теста

. ____   _   __ _ _ 
/\\/___'_ __ _ _(_)_ __ __ _ \ \ \ \ 
(()\___ | '_ | '_| | '_ \/ _` | \ \ \ \ 
\\/ ___)| |_)| | | | | || (_| | )))) 
    ' |____| .__|_| |_|_| |_\__, |//// 
=========|_|==============|___/=/_/_/_/ 
:: Spring Boot ::  (v1.4.2.RELEASE) 

2016-11-27 16:22:08.254 INFO 9029 --- [   main] no.avec.controller.HealthControllerTest : Starting HealthControllerTest on ducati.local with PID 9029 (started by avec in /Users/avec/Projects/RESTdemo) 
2016-11-27 16:22:08.257 DEBUG 9029 --- [   main] no.avec.controller.HealthControllerTest : Running with Spring Boot v1.4.2.RELEASE, Spring v4.3.4.RELEASE 
2016-11-27 16:22:08.257 INFO 9029 --- [   main] no.avec.controller.HealthControllerTest : No active profile set, falling back to default profiles: default 
2016-11-27 16:22:09.294 INFO 9029 --- [   main] no.avec.controller.HealthControllerTest : Started HealthControllerTest in 1.421 seconds (JVM running for 2.132) 

MockHttpServletRequest: 
     HTTP Method = GET 
     Request URI = /health 
     Parameters = {} 
      Headers = {Accept=[application/json]} 

Handler: 
      Type = org.springframework.web.servlet.resource.ResourceHttpRequestHandler 

Async: 
    Async started = false 
    Async result = null 

Resolved Exception: 
      Type = null 

ModelAndView: 
     View name = null 
      View = null 
      Model = null 

FlashMap: 
     Attributes = null 

MockHttpServletResponse: 
      Status = 404 
    Error message = null 
      Headers = {} 
    Content type = null 
      Body = 
    Forwarded URL = null 
    Redirected URL = null 
      Cookies = [] 

java.lang.AssertionError: Status 
Expected :200 
Actual :404 
+0

Вы также с помощью веб-безопасности Config? –

+1

Вероятно, ваш контроллер не будет поднят весной, когда будет создан контекст для вашего теста. Попробуйте использовать '@SpringBootTest' в сочетании с '@AutoConfigureMockMvc', как описано здесь: http://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/test/autoconfigure/web/servlet/ WebMvcTest.html. – Tom

+0

Когда вы * скручиваете * конечную точку '/ health', которую вы вызываете: конечная точка исполнительного механизма Spring Boot или ваш пользовательский контроллер?IMHO, конечная точка привода - причина того, что «curl -i http: // localhost: 8080/health» успешна, и ваш контроллер не получает вообще –

ответ

2

Судя по @Path и @GET аннотациями вы используете JAX-RS, а не Spring MVC. @WebMvcTest специально предназначен для тестирования веб-фрагмента, реализованного с использованием Spring MVC. Он отфильтровывает компоненты, которые не являются контроллерами Spring MVC, поэтому он не будет работать с веб-API, реализованным с использованием JAX-RS.

+0

Да, я использую JAX-RS. Я создал контроллер Spring, а затем он сработал. Тем не менее, я получил JAX-RS Controller для тестирования с подсказкой от @Tom в комментарии выше (начальный вопрос) – Avec

+0

Я играл с этой идеей некоторое время назад (пока я пытался использовать ее для restdocs), и это _возможно. Вам необходимо зарегистрировать экземпляр [ServletContainer] (https://github.com/spring-projects/spring-boot/blob/v1.4.2.RELEASE/spring-boot-autoconfigure/src/main/java/org/ springframework/boot/autoconfigure/jersey/JerseyAutoConfiguration.java # L149) (который является фильтром и сервлетом) с помощью MockMvcBuilders. Раньше я пытался воспроизвести те же результаты, но я не мог этого сделать. Не уверен, что я сделал в прошлый раз. Все, что я помню, это то, что это было действительно взломано :-) –

+0

@peeskillet Интересно, и может быть, это то, чем я занимаюсь. Плохо вы не помните. Хотя хакки редко бывают хорошими. – Avec

0

Когда я смотрю на ваш класс контроллера, это немного запутанно. Вы используете @Controller, а затем @Path и @GET аннотации, что означает, что вы используете Джерси. Вместо этого я рекомендую использовать @Component. Хотя, @Controller распространяется @Component, но все же ....

В любом случае, вы должны использовать org.springframework.boot.test.web.client.TestRestTemplate для тестирования ресурсов вашего отдыха. Например,

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


    @Autowired 
    private TestRestTemplate restTemplate; 

    @Test 
    public void contextLoads() { 
     final ResponseEntity<Health> entity = this.restTemplate.getForEntity("/health", Health.class); 
     assertThat(entity.getStatusCode()).isEqualTo(OK); 
    } 

} 

Это должно сработать для вас.

Я добавляю pom.xml, который показывает, какие зависимости вам необходимо добавить к вашему pom.xml

<?xml version="1.0" encoding="UTF-8"?> 
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
    <modelVersion>4.0.0</modelVersion> 

    <groupId>no.hassan.bones</groupId> 
    <artifactId>spring-boot-backbone</artifactId> 
    <version>0.0.1-SNAPSHOT</version> 
    <packaging>jar</packaging> 

    <name>spring-boot-exmaple-jersey-mvc</name> 
    <description>Doing Spring Boot with jersey and spring web-mvc</description> 

    <parent> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-parent</artifactId> 
     <version>1.4.2.RELEASE</version> 
     <relativePath/> <!-- lookup parent from repository --> 
    </parent> 

    <properties> 
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
     <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> 
     <java.version>1.8</java.version> 
    </properties> 

    <dependencies> 

     <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-actuator</artifactId> 
     </dependency> 

     <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-web</artifactId> 
     </dependency> 

     <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-jersey</artifactId> 
     </dependency> 

     <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-test</artifactId> 
      <scope>test</scope> 
     </dependency> 

    </dependencies> 

    <build> 
     <plugins> 
      <plugin> 
       <groupId>org.springframework.boot</groupId> 
       <artifactId>spring-boot-maven-plugin</artifactId>    
      </plugin> 
     </plugins> 
    </build> 


</project> 

Как вы можете видеть, что я использую как Spring MVC т.е. spring-boot-starter-web и трикотаж, а также spring-boot-starter-jersey , Помните, что вам нужно добавить класс @Configuration, который зарегистрирует конечные точки отдыха Jerse. Вот это класс образец для вас

import javax.ws.rs.ApplicationPath; 

import org.glassfish.jersey.server.ResourceConfig; 
import org.springframework.context.annotation.Configuration; 

/** 
* @author Iftikhar Ul Hassan 
*/ 

@Configuration 
@ApplicationPath("/rest") 
public class JerseyConfig extends ResourceConfig { 

    public JerseyConfig() { 
     packages("package.path.where.HealthController.resides"); 

    } 
} 

Теперь вы можете обслуживать джерси отдыха enpoints под /rest/**

+0

Я пробовал это, но получил «Неудовлетворенную зависимость, выраженную через поле« restTemplate »;' – Avec

+0

Теперь я вижу, что было непонятно, что я использовал JAX-RS. Я обновил это в своем сообщении. – Avec

+0

Вы пытались удалить аннотацию '@ Contorller' и попробовали' @ Component'? Было бы приятно видеть ваше pom.xml – Hasasn

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