Je suis assez nouveau dans Spring et j'essaie de faire quelques tests d'intégration de base pour un @Controller
.
@RunWith(SpringRunner.class)
@WebMvcTest(DemoController.class)
public class DemoControllerIntegrationTests {
@Autowired
private MockMvc mvc;
@MockBean
private DemoService demoService;
@Test
public void index_shouldBeSuccessful() throws Exception {
mvc.perform(get("/home").accept(MediaType.TEXT_HTML)).andExpect(status().isOk());
}
}
mais j'obtiens
Java.lang.IllegalStateException: Impossible de charger ApplicationContext Causée par: org.springframework.beans.factory.BeanCreationException: Erreur lors de la création d'un bean avec le nom 'jpaMappingContext': L'invocation de la méthode init a échoué; L'exception imbriquée est Java.lang.IllegalArgumentException: au moins un métamodèle JPA doit être présent! !__. Causé par: Java.lang.IllegalArgumentException: au moins un métamodèle JPA doit être présent!
Contrairement à la plupart des gens qui publient cette erreur, je ne souhaite pas utiliser JPA pour cela. Est-ce que j'essaie d'utiliser @WebMvcTest
de manière incorrecte? Comment retrouver la magie du printemps qui invite JPA à cette fête?
Supprimez tout @EnableJpaRepositories
ou @EntityScan
de votre classe SpringBootApplication
à la place, procédez comme suit:
package com.tdk;
@SpringBootApplication
@Import({ApplicationConfig.class })
public class TdkApplication {
public static void main(String[] args) {
SpringApplication.run(TdkApplication.class, args);
}
}
Et mettez-le dans une classe de configuration séparée:
package com.tdk.config;
@Configuration
@EnableJpaRepositories(basePackages = "com.tdk.repositories")
@EntityScan(basePackages = "com.tdk.domain")
@EnableTransactionManagement
public class ApplicationConfig {
}
Et voici les tests:
@RunWith(SpringRunner.class)
@WebAppConfiguration
@WebMvcTest
public class MockMvcTests {
}
Vous pouvez également définir une classe de configuration personnalisée dans votre scénario de test, comprenant uniquement le contrôleur (ainsi que ses dépendances), afin de forcer Spring à utiliser this context.
Veuillez noter que vous aurez toujours accès à MockMvc
et à d'autres bienfaits dans votre scénario de test, si elle est WebMvcTest
annotée.
@RunWith(SpringRunner.class)
@WebMvcTest(DemoController.class)
public class DemoControllerIntegrationTests {
@Autowired
private MockMvc mvc;
@MockBean
private DemoService demoService;
@Test
public void index_shouldBeSuccessful() throws Exception {
mvc.perform(get("/home").accept(MediaType.TEXT_HTML)).andExpect(status().isOk());
}
@Configuration
@ComponentScan(basePackageClasses = { DemoController.class })
public static class TestConf {}
J'ai eu le même problème. @WebMvcTest recherche une classe annotée avec @SpringBootApplication (dans le même répertoire ou plus haut dans la structure de votre application si elle n'en trouve pas). Vous pouvez lire comment cela fonctionne @ https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-testing-spring-boot-applications-testing-autoconfigured-mvc- tests .
Si votre classe annotée avec @SpringBootApplication comporte également @EntityScan/@ EnableJpaRepositories, cette erreur se produit. Parce que vous avez ces annotations avec @SpringBootApplication et que vous vous moquez du service (vous n'utilisez donc aucun JPA). J'ai trouvé une solution de contournement qui n'est peut-être pas la plus jolie, mais qui fonctionne pour moi.
Placez cette classe dans votre répertoire de test (la racine). @WebMvcTest trouvera cette classe avant votre classe Application actuelle. Dans cette classe, vous n'avez pas besoin d'ajouter @ EnableJpaRepositories/@ EntityScan.
@SpringBootApplication(scanBasePackageClasses = {
xxx.service.PackageMarker.class,
xxx.web.PackageMarker.class
})
public class Application {
}
Et votre test aura le même aspect.
@RunWith(SpringRunner.class)
@WebMvcTest
@WithMockUser
public class ControllerIT {
@Autowired
private MockMvc mockMvc;
@MockBean
private Service service;
@Test
public void testName() throws Exception {
// when(service.xxx(any(xxx.class))).thenReturn(xxx);
// mockMvc.perform(post("/api/xxx")...
// some assertions
}
}
J'espère que cela t'aides!
Si quelqu'un utilise Spring Boot et ne veut pas supprimer @EntityScan
et @EnableJpaRepositories
, vous pouvez supprimer l'annotation @WebMvcTest
de votre classe de test et ajouter les éléments suivants à la place:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
public class DemoControllerIntegrationTests {
@Autowired
private MockMvc mvc;
//...
}
et vous serez en mesure d'autowire MockMvc
et de l'utiliser.