0

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")
user1182625
  • 145
  • 2
  • 15

1 Answers1

0

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.

rieckpil
  • 10,470
  • 3
  • 32
  • 56
  • thnx, I know, but it was strange...when I added this (after I tried with @SpringBootTest) it worked, but then again it failed, and finally, I figure it out. It was because I named one repository class in test same as in main. So Spring Boot was confused but react differently all the time, and that is strange. It should works or not. So, I delete this class with same name (without Component annotation), removed that annotation and I have only @DataJpaTest and it works perfectly. – user1182625 Jun 15 '20 at 08:53