Hi,
sorry. I tried my best but I coudn't find a solution. I have read this https://spring.io/blog/2016/04/15/testing-improvements-in-spring-boot-1-4 and love the possibility to test my layers independently. But for some reason it's not working. I have a simple web / jpa application.
My controller test configuration is
@RunWith(SpringRunner.class)
@WebMvcTest(ReportController.class)
public class ReportControllerTest {
My Bootstrap class
@SpringBootApplication
@EnableJpaRepositories
@EnableSpringDataWebSupport
@EnableTransactionManagement
@EntityScan(basePackageClasses =
{Bootstrap.class, Jsr310JpaConverters.class})
public class Bootstrap extends WebMvcConfigurerAdapter {
As soon as I start my test the application fails to start and logs
Caused by: java.lang.IllegalArgumentException: At least one JPA metamodel must be present!
at org.springframework.util.Assert.notEmpty(Assert.java:276) ~[spring-core-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.data.jpa.mapping.JpaMetamodelMappingContext.<init>(JpaMetamodelMappingContext.java:52) ~[spring-data-jpa-1.10.2.RELEASE.jar:na]
at org.springframework.data.jpa.repository.config.JpaMetamodelMappingContextFactoryBean.createInstance(JpaMetamodelMappingContextFactoryBean.java:71) ~[spring-data-jpa-1.10.2.RELEASE.jar:na]
at org.springframework.data.jpa.repository.config.JpaMetamodelMappingContextFactoryBean.createInstance(JpaMetamodelMappingContextFactoryBean.java:26) ~[spring-data-jpa-1.10.2.RELEASE.jar:na]
at org.springframework.beans.factory.config.AbstractFactoryBean.afterPropertiesSet(AbstractFactoryBean.java:134) ~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637) ~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574) ~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
... 44 common frames omitted
If I remove the @EnableJpaRepositories annotation everything works fine.
I hope you can help me with this. I couldgo back to @SpringBootTest but I really would like to use the new annotation as they make testing much faster and easier.
Edit: I'm using gradle with
classpath org.springframework.boot:spring-boot-gradle-plugin:1.4.0.RELEASE
mavenBom org.springframework.cloud:spring-cloud-dependencies:Brixton.SR5
Comment From: philwebb
By using @EnableJpaRepositories you are explicitly telling Spring Boot's auto-configuration to back off and that you'll handle Spring Data yourself. I think what's happening is that @WebMvcTest is turning off JPA (i.e. not finding your @Entity classes) but @EnableJpaRepositories is still active so it complains that it can't find any JPA models.
Is there any reason why you need to explicitly use the @EnableJpaRepositories annotation? If you instead depend completely on auto-configuration then things should work.
Comment From: Writtscher
I guess I missed something in the docs, didn't know that. Thanks @philwebb, works now - cheers!
Comment From: snicoll
Also, I'd recommend moving those customizations from your main @SpringBootApplication if you can. The new test infrastructure auto-detects your spring boot class (which is great to get proper base package for classpath scanning) but anything that's actually defined there must be available in all slices somehow. Another alternative is to specify the spring boot class to use but that's more code.
Thanks for the feedback!
Comment From: xak2000
@snicoll I'd like to say thanks you very much!
I was struggling with this problem in hours.
My @SpringBootApplication class also has this annotations:
@EntityScan
@EnableJpaAuditing
@EnableJpaRepositories
@EnableTransactionManagement
@IntegrationComponentScan
@EnableCaching
And it also causes spring boot's unhandled mvc exception handler not in play when controller throw some unexpected exception. For example:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
public class ControllerTests {
@Autowired
private MockMvc mvc;
@Test
public void testInternalServerError() throws Exception {
mvc.perform(get("/api/data"))
.andExpect(status().isInternalServerError());
}
}
just not worked!
Instead of catching the status 500, the test method throws the exception that controller throws.
But when I moved all these spring-boot annotations from @SpringBootApplication class to new @Configuration class - all started to work!
Comment From: raspacorp
@philwebb What about the case when some of your components are not in the same base package than the application configuration class and you need to use @EnableJpaRepositories (e.g. http://stackoverflow.com/questions/29221645/cant-autowire-repository-annotated-interface-in-spring-boot) or when needing to use @EnableJpaAuditing.
Comment From: icougil
Hi!
We've arrived to this issue because trying to run our repository tests and we've raised the same issue. Our repositories are based in our package com.example.auth.repository and our entities in com.example.auth.domain (which are based in another maven module).
Even we've added the @EntityScan and @EnableJpaRepositories (with the proper packages included) in our @Configuration test file, it seems that Spring data is unable to recognize where are our Entities:
Caused by: java.lang.IllegalArgumentException: At least one JPA metamodel must be present!
at org.springframework.util.Assert.notEmpty(Assert.java:276)
at org.springframework.data.jpa.mapping.JpaMetamodelMappingContext.<init>(JpaMetamodelMappingContext.java:52)
at org.springframework.data.jpa.repository.config.JpaMetamodelMappingContextFactoryBean.createInstance(JpaMetamodelMappingContextFactoryBean.java:71)
at org.springframework.data.jpa.repository.config.JpaMetamodelMappingContextFactoryBean.createInstance(JpaMetamodelMappingContextFactoryBean.java:26)
at org.springframework.beans.factory.config.AbstractFactoryBean.afterPropertiesSet(AbstractFactoryBean.java:134)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1642)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1579)
... 39 more
What we should do?
Comment From: snicoll
What we should do?
Hi, not comment on closed issues and ask questions on stackoverflow ;-) thanks.
Comment From: subramk
This is still valid now . Thanks a lot .. I struggled with this for all of two days and now my @WebMvcTest works. I am on Java 17 and Spring Boot 3.2.0 and today is 16th Dec 2023 ! . It was so bad that I started to think "Why the hell will a sliced test annotation like @WebMvcTest have to do anything with loading EntityManager". Innumerable hours of googling did nt seem to help till I stumbled upon this. Thank you once again .
Comment From: kasparhzr
This is still valid now .
Same here. It is still valid :)