使用@WebMvcTest获取"必须至少存在一个JPA元模型"

Bra*_*ace 22 java integration-testing spring-mvc spring-data-jpa spring-boot

我是Spring的新手,试图为a做一些基本的集成测试@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());
    }
}
Run Code Online (Sandbox Code Playgroud)

但我得到了

java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaMappingContext': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: At least one JPA metamodel must be present!
Caused by: java.lang.IllegalArgumentException: At least one JPA metamodel must be present!

与发布此错误的大多数人不同,我不想为此使用JPA.我试图使用@WebMvcTest不正确吗?我怎样才能找到邀请JPA参加这个派对的Spring魔术呢?

Nuñ*_*ada 14

删除任何@EnableJpaRepositories@EntityScan从您的SpringBootApplication班级,而不是这样做:

package com.tdk;

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

    public static void main(String[] args) {
        SpringApplication.run(TdkApplication.class, args);
    }
}
Run Code Online (Sandbox Code Playgroud)

并将它放在一个单独的配置类中:

package com.tdk.config;

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

}
Run Code Online (Sandbox Code Playgroud)

在这里测试:

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

}
Run Code Online (Sandbox Code Playgroud)


Jus*_*n K 5

我有同样的问题。@WebMvcTest寻找一个用@SpringBootApplication注释的类(如果找不到,则在同一目录或更高的应用程序结构中)。您可以在https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-testing-spring-boot-applications-testing-autoconfigured-mvc-tests中阅读其工作原理。

如果使用@SpringBootApplication注释的类也具有@EntityScan / @ EnableJpaRepositories,则会发生此错误。因为您在@SpringBootApplication中具有这些批注,并且正在模拟服务(因此实际上不使用任何JPA)。我找到了一种解决方法,它可能不是最漂亮的,但对我有用。

将此类放在您的测试目录(根目录)中。@WebMvcTest将在您实际的Application类之前找到该类。在此类中,您不必添加@ EnableJpaRepositories / @ EntityScan。

@SpringBootApplication(scanBasePackageClasses = {
    xxx.service.PackageMarker.class,
    xxx.web.PackageMarker.class
})
public class Application {
}
Run Code Online (Sandbox Code Playgroud)

和您的测试将看起来相同。

@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
    }
}
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助!


Moh*_*ish 5

另外,您可以在测试用例中定义一个自定义配置类,仅包括控制器(及其依赖项),以强制Spring使用上下文。
请注意,如果有注释,您仍然可以使用MockMvc测试用例和其他优点WebMvcTest

@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 {}
Run Code Online (Sandbox Code Playgroud)