Spring Boot DataJpaTest失败,并出现java.lang.IllegalStateException:原因:给定类型必须是接口 [英] Spring Boot DataJpaTest fail with java.lang.IllegalStateException:Caused by: Given type must be an interface
问题描述
准确地说,要看我有什么错误.
如果我使用Intellij Maven Install,则会收到此异常(这很奇怪,因为我具有此依赖关系,并且如果我没有记错的话,默认情况下应在spring-starter-test中将其设置为默认值):
Caused by: java.lang.ClassNotFoundException: ch.qos.logback.classic.turbo.TurboFilter
但是,如果我直接在有问题的测试类中开始测试,则会出现此异常:
o.s.test.context.TestContextManager : Caught exception while allowing TestExecutionListener [org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@217ed35e] to prepare test instance [mypackage.DataBaseTest@279fedbd]
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:125) ~[spring-test-5.1.4.RELEASE.jar:5.1.4.RELEASE]
...
Caused by: java.lang.IllegalArgumentException: Given type must be an interface!
at org.springframework.util.Assert.isTrue(Assert.java:118) ~[spring-core-5.1.4.RELEASE.jar:5.1.4.RELEASE]
对于第一个例外(Maven-> Install),我不明白,我在那个类中有那个jar.
-External Libraries
|
|
|--- Maven: ch.qos.logback:logback-classic:1.2.3
|---logback-classic-1.2.3.jar
|
|---turbo
|
|---TurboFilter
对于第二个例外,我无法理解@DataJpaTest是否创建了所有内容.我尝试使用@SpringBootTest(认为可能是与自动装配的存储库一起使用的@Service).
我正在将Spring Boot 2,jUnit5与没有jUnit4的Spring-boot-starter-test一起使用.
我的pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
...
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>weblogic</groupId>
<artifactId>wljmsclient</artifactId>
<version>12.1.1</version>
<scope>provided</scope>
</dependency>
<!-- Tomcat embedded container-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.oracle.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>12.2.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.6.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.200</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
<scope>test</scope>
</dependency>
应用程序配置:
@Configuration
@EnableJms
@EnableJpaRepositories
@PropertySource({"classpath:some.properties"})
public class ApplicationConfig {
...
private Properties getJNDiProperties() {
final Properties jndiProps = new Properties();
jndiProps.setProperty(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
return jndiProps;
}
@Bean
public JndiTemplate jndiTemplate() {
final JndiTemplate jndiTemplate = new JndiTemplate();
jndiTemplate.setEnvironment(getJNDiProperties());
return jndiTemplate;
}
application.properties文件:
spring.datasource.jndi-name=jdbc/myDataSource
spring.jpa.database-platform=org.hibernate.dialect.Oracle10gDialect
spring.jpa.show-sql=false
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.generate-ddl=false
我没有任何测试应用程序配置.
application.properties为空,我什么也没有,因为我认为@DataJpaTest将为我创建所有内容.其他测试也不错,但只有@DataJpaTest的测试类因提到的异常而失败.
package myPackage;
import myPackage.repository.MyRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.persistence.EntityManager;
import javax.sql.DataSource;
import static org.assertj.core.api.Assertions.assertThat;
@DataJpaTest
public class DataBaseTest {
@Autowired
private DataSource dataSource;
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private EntityManager entityManager;
@Autowired
private MyRepository myRepository;
@Test
public void injectedComponentsAreNotNull(){
assertThat(dataSource).isNotNull();
assertThat(jdbcTemplate).isNotNull();
assertThat(entityManager).isNotNull();
assertThat(myRepository).isNotNull();
}
}
但是,如果我删除@DataJpaTest并添加@SpringBootConfiguration和@EnableAutoConfiguration,则所有自动装配的对象都为空.
我不明白为什么Spring Boot不能自动连接这些对象.
已更新
因此,仅使用@DataJpaTest我就添加了@Import(MyRepository.class),但是我有相同的例外.
Maven->安装
Caused by: java.lang.ClassNotFoundException: ch.qos.logback.classic.turbo.TurboFilter
那堂课在那里!
IntelliJ->运行测试类
o.s.test.context.TestContextManager : Caught exception while allowing TestExecutionListener [org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@217ed35e] to prepare test instance [mypackage.DataBaseTest@279fedbd]
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:125) ~[spring-test-5.1.4.RELEASE.jar:5.1.4.RELEASE]
...
Caused by: java.lang.IllegalArgumentException: Given type must be an interface!
at org.springframework.util.Assert.isTrue(Assert.java:118) ~[spring-core-5.1.4.RELEASE.jar:5.1.4.RELEASE]
更新2
我之所以拥有ClassNotFoundException ch.qos.logback.classic.turbo.Filter的原因是因为我遇到了slf4j和maven surefire的问题,所以我排除了logback:
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<configuration>
<classpathDependencyExcludes>
<classpathDependencyExcludes>ch.qos.logback:logback-classic</classpathDependencyExcludes>
</classpathDependencyExcludes>
</configuration>
</plugin>
我删除了此配置,但现在有与直接从IntelliJ直接运行相同的例外.
Caused by: java.lang.IllegalArgumentException: Given type must be an interface!
更新3
最后,我取得了进步.我需要的是@EnableAutoConfiguration. 我以为@DataJpaTest可以为我做事情,但是显然,它有问题.
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Schema "MYSCHEMA" not found; SQL statement:
我的实体如下:
@Getter
@Setter
@ToString
@Builder(toBuilder=true)
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(of = "logId")
@Entity
@Table(name = "MY_TABLE", schema = "MYSCHEMA", catalog = "")
public class MyEntity {
我需要一个用于测试的架构.
我尝试过此方法,但没有帮助:
@TestPropertySource(properties = "spring.jpa.properties.hibernate.default_schema=PETRA")
@DataJpaTest
不需要@EnableAutoConfiguration
,因为注释使每个必需的部分都可以测试应用程序的这一部分:
// ... and some more
@BootstrapWith(DataJpaTestContextBootstrapper.class)
@ExtendWith(SpringExtension.class)
@OverrideAutoConfiguration(enabled = false)
@TypeExcludeFilters(DataJpaTypeExcludeFilter.class)
@Transactional
@AutoConfigureCache
@AutoConfigureDataJpa
@AutoConfigureTestDatabase
@AutoConfigureTestEntityManager
@ImportAutoConfiguration
public @interface DataJpaTest {
}
重要的是要提到,在@DataJpaTest
中,Spring将默认使用嵌入式内存数据库:
* By default, tests annotated with {@code @DataJpaTest} are transactional and roll back
* at the end of each test. They also use an embedded in-memory database (replacing any
* explicit or usually auto-configured DataSource). The
* {@link AutoConfigureTestDatabase @AutoConfigureTestDatabase} annotation can be used to
* override these settings.
这就是为什么您看到H2数据库输出而不是Oracle的原因.默认情况下,Spring应该使用spring.jpa.hibernate.ddl-auto=create-drop
来确保您的表存在.
使用@Table(name = "MY_TABLE", schema = "MYSCHEMA", catalog = "")
对JPA实体中的架构进行硬编码时,必须确保嵌入式H2也使用该架构.
首先尝试从@Table
批注中删除schema
,然后查看它是否有效.然后,您可以在application.properties
中全局配置架构,并使用@TestPropertySource(properties = "spring.jpa.properties.hibernate.default_schema=PETRA")
进行测试.
以下 StackOverflow问题可能也有帮助. /p>
To be precise depends on what error I have.
If I go with Intellij Maven Install, I get this exception (which is strange because I have this dependency and it should be by default in spring-starter-test if I am not wrong):
Caused by: java.lang.ClassNotFoundException: ch.qos.logback.classic.turbo.TurboFilter
But if I start test directly in problematic test class I get this exception:
o.s.test.context.TestContextManager : Caught exception while allowing TestExecutionListener [org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@217ed35e] to prepare test instance [mypackage.DataBaseTest@279fedbd]
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:125) ~[spring-test-5.1.4.RELEASE.jar:5.1.4.RELEASE]
...
Caused by: java.lang.IllegalArgumentException: Given type must be an interface!
at org.springframework.util.Assert.isTrue(Assert.java:118) ~[spring-core-5.1.4.RELEASE.jar:5.1.4.RELEASE]
For the first exception (Maven->Install) I don't understand, I have that jar with that class.
-External Libraries
|
|
|--- Maven: ch.qos.logback:logback-classic:1.2.3
|---logback-classic-1.2.3.jar
|
|---turbo
|
|---TurboFilter
For the second exception, I cannot understand if @DataJpaTest creates everything. I tried with @SpringBootTest (thought it could be @Service I use with autowired repositories).
I am using Spring Boot 2, jUnit5 with Spring-boot-starter-test with no jUnit4.
My pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
...
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>weblogic</groupId>
<artifactId>wljmsclient</artifactId>
<version>12.1.1</version>
<scope>provided</scope>
</dependency>
<!-- Tomcat embedded container-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.oracle.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>12.2.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.6.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.200</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
<scope>test</scope>
</dependency>
Application configuration:
@Configuration
@EnableJms
@EnableJpaRepositories
@PropertySource({"classpath:some.properties"})
public class ApplicationConfig {
...
private Properties getJNDiProperties() {
final Properties jndiProps = new Properties();
jndiProps.setProperty(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
return jndiProps;
}
@Bean
public JndiTemplate jndiTemplate() {
final JndiTemplate jndiTemplate = new JndiTemplate();
jndiTemplate.setEnvironment(getJNDiProperties());
return jndiTemplate;
}
application.properties file:
spring.datasource.jndi-name=jdbc/myDataSource
spring.jpa.database-platform=org.hibernate.dialect.Oracle10gDialect
spring.jpa.show-sql=false
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.generate-ddl=false
I don't have any test application configuration.
application.properties is empty, I have nothing because I thought @DataJpaTest will create everything for me. Other tests are good but only test class with @DataJpaTest failed with a mentioned exception.
package myPackage;
import myPackage.repository.MyRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.persistence.EntityManager;
import javax.sql.DataSource;
import static org.assertj.core.api.Assertions.assertThat;
@DataJpaTest
public class DataBaseTest {
@Autowired
private DataSource dataSource;
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private EntityManager entityManager;
@Autowired
private MyRepository myRepository;
@Test
public void injectedComponentsAreNotNull(){
assertThat(dataSource).isNotNull();
assertThat(jdbcTemplate).isNotNull();
assertThat(entityManager).isNotNull();
assertThat(myRepository).isNotNull();
}
}
But if I remove @DataJpaTest and add @SpringBootConfiguration and @EnableAutoConfiguration instead all autowired objects are null.
I don't understand why Spring Boot doesn't autowired these objects.
UPDATED
So, with just @DataJpaTest I add @Import(MyRepository.class) but I have the same exceptions.
Maven->Install
Caused by: java.lang.ClassNotFoundException: ch.qos.logback.classic.turbo.TurboFilter
And the class is there!!!
IntelliJ->Run test class
o.s.test.context.TestContextManager : Caught exception while allowing TestExecutionListener [org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@217ed35e] to prepare test instance [mypackage.DataBaseTest@279fedbd]
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:125) ~[spring-test-5.1.4.RELEASE.jar:5.1.4.RELEASE]
...
Caused by: java.lang.IllegalArgumentException: Given type must be an interface!
at org.springframework.util.Assert.isTrue(Assert.java:118) ~[spring-core-5.1.4.RELEASE.jar:5.1.4.RELEASE]
UPDATE 2
The reason why I had ClassNotFoundException ch.qos.logback.classic.turbo.Filter was because I had the problem with slf4j and maven surefire so I exclude logback:
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<configuration>
<classpathDependencyExcludes>
<classpathDependencyExcludes>ch.qos.logback:logback-classic</classpathDependencyExcludes>
</classpathDependencyExcludes>
</configuration>
</plugin>
I removed this configuration and now I have the same exception as I am running directly from IntelliJ.
Caused by: java.lang.IllegalArgumentException: Given type must be an interface!
UPDATE 3
Finally, I make progress. What I needed was @EnableAutoConfiguration. I thought @DataJpaTest will do things for me, but obviously, it has a problem.
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Schema "MYSCHEMA" not found; SQL statement:
I have Entity like:
@Getter
@Setter
@ToString
@Builder(toBuilder=true)
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(of = "logId")
@Entity
@Table(name = "MY_TABLE", schema = "MYSCHEMA", catalog = "")
public class MyEntity {
I need a schema for TEST.
I tried with this, but it didn't help:
@TestPropertySource(properties = "spring.jpa.properties.hibernate.default_schema=PETRA")
You don't need @EnableAutoConfiguration
for your @DataJpaTest
, as the annotation is enabling every required part for testing this slice of the application:
// ... and some more
@BootstrapWith(DataJpaTestContextBootstrapper.class)
@ExtendWith(SpringExtension.class)
@OverrideAutoConfiguration(enabled = false)
@TypeExcludeFilters(DataJpaTypeExcludeFilter.class)
@Transactional
@AutoConfigureCache
@AutoConfigureDataJpa
@AutoConfigureTestDatabase
@AutoConfigureTestEntityManager
@ImportAutoConfiguration
public @interface DataJpaTest {
}
It's important to mention that with @DataJpaTest
Spring will use an embedded in-memory database by default:
* By default, tests annotated with {@code @DataJpaTest} are transactional and roll back
* at the end of each test. They also use an embedded in-memory database (replacing any
* explicit or usually auto-configured DataSource). The
* {@link AutoConfigureTestDatabase @AutoConfigureTestDatabase} annotation can be used to
* override these settings.
That's why you see the H2 database output and not Oracle. By default, Spring should use spring.jpa.hibernate.ddl-auto=create-drop
to take care that your tables are present.
As you hardcode the schema inside your JPA entity with @Table(name = "MY_TABLE", schema = "MYSCHEMA", catalog = "")
you have to ensure that the embedded H2 also uses this schema.
First try to remove schema
from the @Table
annotation and see if it works. Then you can globally configure your schema inside your application.properties
and use @TestPropertySource(properties = "spring.jpa.properties.hibernate.default_schema=PETRA")
for your test.
The following StackOverflow question might also help.
这篇关于Spring Boot DataJpaTest失败,并出现java.lang.IllegalStateException:原因:给定类型必须是接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!