2017-10-14 4 views
1

Je suis nouveau au concept de test unitaire avec les contrôleurs Spring. Je suis quelques exemples que j'ai trouvés en ligne et essayant de mettre en application leur stratégie de test. Ceci est mon contrôleur de base:Comment tester l'unité Spring Controller à l'aide d'annotations?

@Controller 
public class GreetingController { 

    @RequestMapping("/greeting") 
    public String greeting(@RequestParam(value = "name2", required = false, defaultValue = "World2") String name2, 
          Model model) { 

     model.addAttribute("name", name2); 
     return "greeting"; 
    } 

} 

Ceci est mon test unitaire:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration 
@WebAppConfiguration 
public class ControllerGreetingTest { 

    private MockMvc mockMvc; 

    @Autowired 
    GreetingController greetingController; 
    @Test 
    public void shouldReturnSomething() throws Exception { 
     mockMvc.perform(get("/greeting")) 
       .andExpect(status().isOk()) 
       .andExpect(view().name("greeting")); 
    } 

} 

Semble assez simple, mais je reçois l'erreur suivante:

java.lang.IllegalStateException: Neither GenericXmlWebContextLoader nor AnnotationConfigWebContextLoader was able to detect defaults, and no ApplicationContextInitializers were declared for context configuration [[email protected] declaringClass = 'com.practice.demo.ControllerGreetingTest', locations = '{}', classes = '{}', inheritLocations = true, initializers = '{}', inheritInitializers = true, name = [null], contextLoaderClass = 'org.springframework.test.context.ContextLoader']

Je suppose que j'ai pour ajouter un paramètre à l'annotation @ContextConfiguration mais ne savez pas quoi inclure.

EDIT = C'est ce que j'ai jusqu'à présent:

public class ControllerGreetingTest { 

    private MockMvc mockMvc; 

    @Before 
    public void setup(){ 
     this.mockMvc = standaloneSetup(new GreetingController()).build(); 
    } 

    @Test 
    public void shouldReturnDefaultString() throws Exception { 
     mockMvc.perform(get("/greeting")) 
       .andExpect(status().isOk()) 
       .andExpect(view().name("greetings")) 
       .andExpect(model().attribute("name","World2")); 
    } 

} 

Il fait le travail, mais il n'utilise pas des annotations de printemps comme je l'ai essayé de le faire avant .. cette approche n'est pas bon si essayer de comprendre pourquoi je garde des erreurs de lecture chaque fois que j'inclue les annotations dans mon fichier de test.

Mon POM:

<dependencies> 
    <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test --> 
    <dependency> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-test</artifactId> 
     <version>1.5.7.RELEASE</version> 
     <scope>test</scope> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-data-mongodb</artifactId> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-thymeleaf</artifactId> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-devtools</artifactId> 
     <optional>true</optional> 
    </dependency> 
    <dependency> 
     <groupId>org.hamcrest</groupId> 
     <artifactId>hamcrest-all</artifactId> 
     <version>1.3</version> 
     <scope>test</scope> 
    </dependency> 
    <dependency> 
     <groupId>junit</groupId> 
     <artifactId>junit</artifactId> 
     <scope>test</scope> 
     <exclusions> 
      <exclusion> 
       <artifactId>hamcrest-core</artifactId> 
       <groupId>org.hamcrest</groupId> 
      </exclusion> 
     </exclusions> 
    </dependency> 
    <dependency> 
     <groupId>org.mockito</groupId> 
     <artifactId>mockito-core</artifactId> 
     <version>1.9.5</version> 
     <scope>test</scope> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework</groupId> 
     <artifactId>spring-test</artifactId> 
     <version>3.2.3.RELEASE</version> 
     <scope>test</scope> 
    </dependency> 
    <dependency> 
     <groupId>junit</groupId> 
     <artifactId>junit</artifactId> 
     <scope>test</scope> 
    </dependency> 
    <!-- https://mvnrepository.com/artifact/org.mongodb/mongo-java-driver --> 
     <dependency> 
      <groupId>org.mongodb</groupId> 
      <artifactId>mongo-java-driver</artifactId> 
      <version>3.4.2</version> 
     </dependency> 
    <dependency> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-dependencies</artifactId> 
     <version>1.5.7.RELEASE</version> 
     <scope>test</scope> 
    </dependency> 

</dependencies> 
+0

Essayez d'utiliser @RunWith (SpringRunner.class) si nous parlons de démarrage du printemps – Antoniossss

+0

@Antoniossss J'utilise botte printemps. Quelle dépendance dois-je inclure dans le pom pour inclure le SpringRunner.class car j'obtiens un 'ne peut pas résoudre le symbole 'SpringRuner'' – dfqupwndguerrillamailde

+0

org.springframework.boot: spring-boot-starter-test – Antoniossss

Répondre

2

Pour les projets avec org.springframework.boot:spring-boot-starter-test peuvent utiliser

@RunWith(SpringRunner.class) 
@SpringBootTest(classes = App.class) 
public class ControllerGreetingTest { 
    ... 
} 

App.class vous est principale classe d'application annotée avec @SpringBootApplication. Mais vous feriez mieux de lire le documentation. Et si vous ne voulez pas inclure (classes = App.class) partie vous pouvez également changer folder structure

Pour les contrôleurs simples, il est possible d'effectuer des tests autonomes simples

@RunWith(SpringRunner.class) 
@WebMvcTest(controllers = ControllerGreeting.class) 
public class ControllerGreetingTest { 
    @Autowired 
    private MockMvc mockMvc; 

    ... 

} 
1

Vous devez utiliser la dépendance spring-boot-starter-test. Il a presque tout pour tester.

Et pour tester la partie contrôleur d'une application de ressort, vous devez utiliser l'annotation @WebMvcTest pour votre classe de test. Avec cette annotation, le ressort chargera le contexte juste pour la partie contrôleur. De plus, vous n'avez pas besoin de configurer la méthode si vous utilisez cette annotation. Vous pouvez simplement autowire mockMvc. Votre classe de test devrait être comme ceci:

@RunWith(SpringRunner.class) 
@WebMvcTest(GreetingController.class) 
public class ControllerGreetingTest { 

    @Autowired 
    private MockMvc mockMvc; 

    @MockBean 
    private SomeServiceClass someServiceClass; 

    @Test 
    public void shouldReturnDefaultString() throws Exception { 
     mockMvc.perform(get("/greeting")) 
      .andExpect(status().isOk()) 
      .andExpect(view().name("greetings")) 
      .andExpect(model().attribute("name","World2")); 
    } 

} 

Note: Votre contrôleur n'a pas de champs autowired. Dans les cas où le contrôleur a des objets autowired comme les objets de service ou de dépôt. vous pouvez simplement vous moquer d'eux avec l'annotation @MockBean comme vous pouvez le voir ci-dessus le code.

Voir this link pour d'autres annotations de tranche de test ressort prévu

0

Il suffit d'ajouter l'annotation @ContextConfiguration et renvoyer une ou plusieurs emplacements de fichier de configuration XML ou une ou plusieurs classes de configuration. Sinon, Spring ne peut pas autowire votre contrôleur, qui devrait être testé.

Exemple: Vous voulez tester un contrôleur, qui utilise MyService via @Autowired:

MyControllerTest: INJECTE le contrôleur, qui doit être testé à l'aide de la classe de configuration MyTestConfig.

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(classes = {MyTestConfig.class}) 
@WebAppConfiguration 
public class MyControllerTest { 

    private MockMvc mockMvc; 

    @Autowired 
    private MyController controller; 

    @Before 
    public void setUp() { 
    mockMvc = MockMvcBuilders.standaloneSetup(controller).build(); 
    } 

    // Tests 
} 

MyTestConfig: Retourne tous les haricots, qui sont nécessaires pour le test. Utilisez Mockito pour simuler les dérives de votre contrôleur, car nous voulons tester uniquement le contrôleur et non la couche de service.

@Configuration 
public class MyTestConfig { 

    @Bean 
    public MyService myService() { 
    return Mockito.mock(MyService.class); 
    } 

    @Bean 
    public MyController myController() { 
    return new MyController(); 
    } 
}