wake-up-neo.com

Abrufen "Es muss mindestens ein JPA-Metamodell mit @WebMvcTest vorhanden sein."

Ich bin ziemlich neu bei Spring und versuche ein paar grundlegende Integrationstests für einen @Controller durchzuführen.

@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());
    }
}

aber ich bekomme

 Java.lang.IllegalStateException: ApplicationContext konnte nicht geladen werden 
 Ursache: org.springframework.beans.factory.BeanCreationException: Fehler beim Erstellen der Bean mit dem Namen 'jpaMappingContext': Fehler beim Aufruf der init-Methode. geschachtelte Ausnahme ist Java.lang.IllegalArgumentException: Es muss mindestens ein JPA-Metamodell vorhanden sein! 
 Ursache: Java.lang.IllegalArgumentException: Es muss mindestens ein JPA-Metamodell vorhanden sein. 

Im Gegensatz zu den meisten Leuten, die diesen Fehler veröffentlichen, möchte ich JPA nicht verwenden . Versuche ich, @WebMvcTest falsch zu verwenden? Wie kann ich die Frühlingszauber finden, die JPA zu dieser Party einlädt?

18
Brad Mace

Entfernen Sie stattdessen einen beliebigen @EnableJpaRepositories oder @EntityScan aus Ihrer SpringBootApplication-Klasse:

package com.tdk;

@SpringBootApplication
@Import({ApplicationConfig.class })
public class TdkApplication {

    public static void main(String[] args) {
        SpringApplication.run(TdkApplication.class, args);
    }
}

Und lege es in eine separate config-Klasse: 

package com.tdk.config;

@Configuration
@EnableJpaRepositories(basePackages = "com.tdk.repositories")
@EntityScan(basePackages = "com.tdk.domain")
@EnableTransactionManagement
public class ApplicationConfig {

}

Und hier die Tests:

@RunWith(SpringRunner.class)
@WebAppConfiguration
@WebMvcTest
public class MockMvcTests {

}
13

Alternativ können Sie in Ihrem Testfall eine benutzerdefinierte Konfigurationsklasse definieren, die nur den Controller (und seine Abhängigkeiten) sowie die Abhängigkeiten dazu umfasst, dass Spring die Verwendung des this - Kontexts erzwingt.
Bitte beachten Sie, dass Sie in Ihrem Testfall weiterhin auf MockMvc und andere Werte zugreifen können, sofern dies WebMvcTest-Anmerkungen ist.

@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 {}
4
Mohnish

Ich hatte das gleiche Problem. @WebMvcTest sucht nach einer Klasse, die mit @SpringBootApplication kommentiert wurde (im selben Verzeichnis oder höher in Ihrer App-Struktur, falls keine gefunden wird). Wie das funktioniert, erfahren Sie unter @ https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-testing-spring-boot-applications-testing-autoconfigured-mvc- Tests .

Wenn Ihre mit @SpringBootApplication kommentierte Klasse ebenfalls @EntityScan/@ EnableJpaRepositories enthält, tritt dieser Fehler auf. Sie haben diese Anmerkungen mit @SpringBootApplication und Sie verspotten den Dienst (verwenden also eigentlich keine JPA). Ich habe einen Workaround gefunden, der vielleicht nicht der Schönste ist, aber für mich funktioniert. 

Fügen Sie diese Klasse in Ihr Testverzeichnis (das Stammverzeichnis) ein. @WebMvcTest findet diese Klasse vor Ihrer eigentlichen Application-Klasse. In dieser Klasse müssen Sie nicht @ EnableJpaRepositories/@ EntityScan hinzufügen.

@SpringBootApplication(scanBasePackageClasses = {
    xxx.service.PackageMarker.class,
    xxx.web.PackageMarker.class
})
public class Application {
}

Und dein Test wird gleich aussehen.

@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
    }
}

Hoffe das hilft!

4
Justin K

Fügen Sie @MockBean(JpaMetamodelMappingContext.class) der Klasse DemoControllerIntegrationTests hinzu:

@RunWith(SpringRunner.class)
@WebMvcTest(DemoController.class)
@MockBean(JpaMetamodelMappingContext.class)
public class DemoControllerIntegrationTests {
    ...
}

Da Sie in Ihrem Test keine Datenbank verwendet haben, gibt Spring diese Ausnahme aus. Indem Sie die Klasse JpaMetamodelMappingContext verspotten, umgehen Sie das erforderliche Metamodell.

1
youhans

Wenn jemand Spring Boot verwendet und @EntityScan und @EnableJpaRepositories nicht entfernen möchte, können Sie die @WebMvcTest-Annotation aus Ihrer Testklasse entfernen und stattdessen Folgendes hinzufügen:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
public class DemoControllerIntegrationTests {
    @Autowired
    private MockMvc mvc;

    //...
}

und Sie können MockMvc automatisch verwenden und verwenden.

1
Mis94