Spring Boot DataJpaTest 失败并显示 java.lang.IllegalStateException:Caused by: Given type must be an interface [英] Spring Boot DataJpaTest fail with java.lang.IllegalStateException:Caused by: Given type must be an interface

查看:40
本文介绍了Spring Boot DataJpaTest 失败并显示 java.lang.IllegalStateException:Caused by: Given type must be an interface的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

准确地说取决于我有什么错误.

To be precise depends on what error I have.

如果我使用 Intellij Maven 安装,我会得到这个异常(这很奇怪,因为我有这个依赖,如果我没有错,它应该默认在 spring-starter-test 中):

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]

对于第一个异常(Maven->Install),我不明白,我有那个类的 jar.

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

对于第二个例外,我无法理解 @DataJpaTest 是否创建了所有内容.我尝试使用@SpringBootTest(我认为它可能是我与自动装配的存储库一起使用的 @Service).

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).

我使用的是 Spring Boot 2、jUnit5 和 Spring-boot-starter-test,没有 jUnit4.

I am using Spring Boot 2, jUnit5 with Spring-boot-starter-test with no jUnit4.

我的 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 文件:

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 是空的,我什么都没有,因为我认为@DataJpaTest 会为我创造一切.其他测试很好,但只有带有 @DataJpaTest 的测试类失败并出现上述异常.

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();
    }
}

但是如果我删除@DataJpaTest 并添加@SpringBootConfiguration 和@EnableAutoConfiguration 而不是所有自动装配的对象都是空的.

But if I remove @DataJpaTest and add @SpringBootConfiguration and @EnableAutoConfiguration instead all autowired objects are null.

我不明白为什么 Spring Boot 不自动装配这些对象.

I don't understand why Spring Boot doesn't autowired these objects.

更新

因此,仅使用 @DataJpaTest 我添加了 @Import(MyRepository.class) 但我有相同的例外.

So, with just @DataJpaTest I add @Import(MyRepository.class) but I have the same exceptions.

Maven->安装

Caused by: java.lang.ClassNotFoundException: ch.qos.logback.classic.turbo.TurboFilter

课程就在那里!!!

IntelliJ->运行测试类

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]

更新 2

我有 ClassNotFoundException ch.qos.logback.classic.turbo.Filter 的原因是因为我有 slf4j 和 maven surefire 的问题,所以我排除了 logback:

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>

我删除了这个配置,现在我有同样的异常,因为我直接从 IntelliJ 运行.

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!

更新 3

最后,我取得了进步.我需要的是@EnableAutoConfiguration.我以为@DataJpaTest 会为我做事,但显然,它有问题.

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:

我有这样的实体:

@Getter
@Setter
@ToString
@Builder(toBuilder=true)
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(of = "logId")
@Entity
@Table(name = "MY_TABLE", schema = "MYSCHEMA", catalog = "")
public class MyEntity {

我需要一个用于 TEST 的架构.

I need a schema for TEST.

我试过这个,但没有帮助:

I tried with this, but it didn't help:

@TestPropertySource(properties = "spring.jpa.properties.hibernate.default_schema=PETRA")

推荐答案

您的 @DataJpaTest 不需要 @EnableAutoConfiguration,因为注释启用了所有必需的用于测试此部分应用程序的部分:

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 {

}

值得一提的是,@DataJpaTest 默认情况下,Spring 将使用嵌入式内存数据库:

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.

这就是您看到 H2 数据库输出而不是 Oracle 的原因.默认情况下,Spring 应该使用 spring.jpa.hibernate.ddl-auto=create-drop 来确保您的表存在.

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.

当您使用 @Table(name = "MY_TABLE", schema = "MYSCHEMA", catalog = "") 对 JPA 实体内的架构进行硬编码时,您必须确保嵌入式 H2 也使用此模式.

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.

首先尝试从 @Table 注释中删除 schema 并查看它是否有效.然后您可以在 application.properties 中全局配置您的架构,并使用 @TestPropertySource(properties = "spring.jpa.properties.hibernate.default_schema=PETRA") 进行测试.

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.

以下StackOverflow 问题也可能有所帮助.

这篇关于Spring Boot DataJpaTest 失败并显示 java.lang.IllegalStateException:Caused by: Given type must be an interface的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆