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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41250177/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 05:46:42  来源:igfitidea点击:

Getting "At least one JPA metamodel must be present" with @WebMvcTest

javaspring-mvcspring-bootspring-data-jpaintegration-testing

提问by Brad Mace

I'm fairly new to Spring, trying to do some basic integration tests for a @Controller.

我对 Spring 相当陌生,试图对@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());
    }
}

but I'm getting

但我得到

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!

Unlike most people posting this error, I don't want to use JPAfor this. Am I trying to use @WebMvcTestincorrectly? How can I track down the Spring magic that's inviting JPA to this party?

与大多数发布此错误的人不同,我不想为此使用 JPA。我是否试图@WebMvcTest错误地使用?我怎样才能找到邀请 JPA 参加这个派对的 Spring 魔法?

回答by Nu?ito de la Calzada

Remove any @EnableJpaRepositoriesor @EntityScanfrom your SpringBootApplicationclass instead do this:

从你的班级中删除任何@EnableJpaRepositories@EntityScanSpringBootApplication而不是这样做:

package com.tdk;

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

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

And put it in a separate config class:

并将其放在单独的配置类中:

package com.tdk.config;

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

}

And here the tests:

这里是测试:

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

}

回答by Mohnish

Alternatively, you can define a custom configuration class inside your test case, including only the controller (plus its dependencies), to force Spring to use thiscontext.
Please note, you'll still have access to MockMvcand other goodness in your test case, if it's WebMvcTestannotated.

或者,您可以在测试用例中定义一个自定义配置类,仅包括控制器(及其依赖项),以强制 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 {}

回答by Justin K

I had the same problem. @WebMvcTest looks for a class annotated with @SpringBootApplication (in the same directory or higher up in your app structure if it doesn't find one). You can read how this works @ https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-testing-spring-boot-applications-testing-autoconfigured-mvc-tests.

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

If your class annotated with @SpringBootApplication also has @EntityScan /@EnableJpaRepositories this error occurs. Because you have these annotations with @SpringBootApplication and you are mocking the service ( so actually not using any JPA ). I found a workaround which may not be the prettiest, but works for me.

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

Place this class in your test directory ( the root ). @WebMvcTest will find this class before your actual Application class. In this class you don't have to add @EnableJpaRepositories/@EntityScan.

将此类放在您的测试目录(根目录)中。@WebMvcTest 会在你的实际应用程序类之前找到这个类。在这个类中,您不必添加@EnableJpaRepositories/@EntityScan。

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

And your test will look the same.

你的测试看起来是一样的。

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

Hope this helps!

希望这可以帮助!

回答by Mis94

If anyone uses Spring boot and don't want to remove @EntityScanand @EnableJpaRepositoriesyou can remove @WebMvcTestannotation from your test class and add the following instead:

如果有人使用 Spring boot 并且不想删除@EntityScan@EnableJpaRepositories您可以@WebMvcTest从测试类中删除注释并添加以下内容:

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

    //...
}

and you will be able to autowire MockMvcand use it.

并且您将能够自动装配MockMvc并使用它。

回答by youhans

Add @MockBean(JpaMetamodelMappingContext.class)to above of class DemoControllerIntegrationTests:

添加@MockBean(JpaMetamodelMappingContext.class)到类的上面DemoControllerIntegrationTests

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

Because you have not used a database in your test, Spring throws this exception. By mocking JpaMetamodelMappingContextclass you will bypass the needed metamodel.

因为您在测试中没有使用数据库,所以 Spring 会抛出这个异常。通过模拟JpaMetamodelMappingContext类,您将绕过所需的元模型。