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
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.
I guess I missed something in the docs, didn't know that. Thanks @philwebb, works now - cheers!
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!
@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!
@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.
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?
What we should do?
Hi, not comment on closed issues and ask questions on stackoverflow ;-) thanks.
Most helpful comment
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!