简体   繁体   中英

@Autowired and UnsatisfiedDependencyException in Spring integration test

I have multi module project with Spring boot and an external server Weblogic.

These are modules:

  • dao
  • service
  • web

    pom.xml (dao) .

It is the work with database (repository, entities)

<?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">
    <parent>
        <artifactId>gov-multiple-modules</artifactId>
        <groupId>gov</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>


    <groupId>com.dao</groupId>
    <artifactId>dao</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <properties>
        <output.directory.jdbc.oracle>${project.basedir}/src/main/resources</output.directory.jdbc.oracle>
    </properties>

    <dependencies>

        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc</artifactId>
            <version>6</version>
            <scope>system</scope>
            <systemPath>${output.directory.jdbc.oracle}/lib/ojdbc6.jar</systemPath>
        </dependency>

    </dependencies>

    <build>
        <plugins>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <argLine>-Dfile.encoding=UTF8</argLine>
                </configuration>
            </plugin>

        </plugins>
    </build>

</project>

  • pom.xml (service )
<?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">
    <parent>
        <artifactId>gov-multiple-modules</artifactId>
        <groupId>gov</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.service</groupId>
    <artifactId>service</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>com.dao</groupId>
            <artifactId>dao</artifactId>
            <version>${version.dao.module}</version>
        </dependency>


        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>${version.mapstruct}</version>
        </dependency>

    </dependencies>


    <build>
          <plugins>

              <plugin>
                  <groupId>org.apache.maven.plugins</groupId>
                  <artifactId>maven-surefire-plugin</artifactId>
                  <configuration>
                      <argLine>-Dfile.encoding=UTF8</argLine>
                  </configuration>
              </plugin>

            <plugin> 
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${version.apache.maven.plugins}</version>
                <groupId>org.apache.maven.plugins</groupId>

                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>${version.mapstruct}</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>
    </build>


</project>

  • pom.xml (web )

    It is the work with requests from clients (Contoroller and RestControllers).

There is an entry point in app.

<?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">
    <parent>
        <artifactId>gov-multiple-modules</artifactId>
        <groupId>gov</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.web</groupId>
    <artifactId>web</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>com.service</groupId>
            <artifactId>service</artifactId>
            <version>${version.service.module}</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>weblogic-war-gov</finalName>
        <plugins>

            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <argLine>-Dfile.encoding=UTF8</argLine>
                </configuration>
            </plugin>


            <plugin> <!--It is for convert beans-->
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${version.apache.maven.plugins}</version>
                <groupId>org.apache.maven.plugins</groupId>

                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>${version.mapstruct}</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>

        </plugins>
    </build>

</project>

  • pom.xml (parrent)
<?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
         https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <modules>
        <module>dao</module>
        <module>service</module>
        <module>web</module>
    </modules>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>gov</groupId>
    <artifactId>gov-multiple-modules</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>

    <name>gov-multiple-modules</name>
    <description>project with Spring Boot for multiple module applications</description>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <version.apache.maven.plugins>3.8.1</version.apache.maven.plugins>
        <version.mapstruct>1.3.0.Final</version.mapstruct>

        <version.apache.common.lang3>3.9</version.apache.common.lang3>
        <version.apache.commons.text>1.8</version.apache.commons.text>
        <version.apache.commons.beanutils>1.9.4</version.apache.commons.beanutils>
        <version.hibernate.validator>6.0.17.Final</version.hibernate.validator>
        <version.reflection>0.9.11</version.reflection>
        <version.dao.module>0.0.1-SNAPSHOT</version.dao.module>
        <version.service.module>0.0.1-SNAPSHOT</version.service.module>

    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</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-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!--This artifact need for testing that to find classes into classpath-->
        <dependency>
            <groupId>org.reflections</groupId>
            <artifactId>reflections</artifactId>
            <version>${version.reflection}</version>
            <scope>test</scope>
        </dependency>


        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>${version.apache.common.lang3}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-text</artifactId>
            <version>${version.apache.commons.text}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>${version.apache.commons.beanutils}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

    </dependencies>

</project>

Into web-module is test-dir.

  • src/test/java/com/web

Here is an repository

  • src/test/java/com/web/dao/repository/company/CompanyReadRepositoryTest.java
public interface CompanyReadRepositoryTest extends CrudRepository<Company, Long> {

    String nameTable = "company";
    String lastEntryQueryFor =
            "select * from (select t.* from " + nameTable + " t order by 1 desc) where rownum = 1";

    @Query(value =lastEntryQueryFor, nativeQuery = true)
    Optional<Company> getLastEntry();
}

I have a class for tests.

@RunWith(SpringRunner.class)
@SpringBootTest
@Sql({
        "classpath:sql/create_sequence_different_types.sql",
        "classpath:sql/create-company.sql",
        "classpath:sql/insert_company.sql"
})
public class CompanyReadServiceTest {


    private static final Logger LOGGER = LoggerFactory.getLogger(CompanyReadServiceTest.class);

    private static String NAME_METHOD_READ_BY_NAME_BOOLEAN = "isByName";


    @Autowired
    private CompanyReadService companyReadService;

    @Autowired
    private CompanyReadRepositoryTest companyReadRepositoryTest;


    @Test
    public void getById() {
...

during class startup, the bean CompanyReadRepositoryTest will not join.

java.lang.IllegalStateException: Failed to load ApplicationContext

at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:132)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:123)
at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:190)

...

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'companyReadServiceTest': Unsatisfied dependency expressed through field 'companyReadService'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.service.read.company.CompanyReadService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject

Added

I little make

@RunWith(SpringRunner.class)
@SpringBootTest(classes = WebSpringBootJarApplication.class )
@AutoConfigureTestDatabase(replace = NONE)
@Sql({
        "classpath:sql/create_sequence_different_types.sql",
        "classpath:sql/create-company.sql",
        "classpath:sql/insert_company.sql"
})
@TestPropertySource(
        locations = "classpath:application-integration-test.properties")
public class CompanyReadServiceTest {


    private static final Logger LOGGER = LoggerFactory.getLogger(CompanyReadServiceTest.class);

    private static String NAME_METHOD_READ_BY_NAME_BOOLEAN = "isByName";

    @Autowired
    private CompanyReadService companyReadService;

    @Autowired
    private CompanyReadRepositoryTest companyReadRepositoryTest;


    @Test
    public void getById() {

...

now is ...

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.web.service.read.company.CompanyReadServiceTest': Unsatisfied dependency expressed through field 'companyReadRepositoryTest'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.web.dao.repository.company.CompanyReadRepositoryTest' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

Any ideas what the errors are? Please.

Solution

You need to move dao.repository in the root test-dir. This directory is com.

src/test/java/com/dao/repository

You repeat the location of repositories in the dao-module.

@RunWith(SpringRunner.class)
@SpringBootTest
@Sql({
        "classpath:sql/create_sequence_different_types.sql",
        "classpath:sql/create-company.sql",
        "classpath:sql/insert_company.sql"
})
@TestPropertySource(
        locations = "classpath:application-integration-test.properties")
public class CompanyReadServiceTest {
...

In your case, CompanyReadRepositoryTest is not annotated with any bean definition annotation(like @Component and the ones that extend it). Spring does not recognize any bean of the needed type and cannot inject it in your property.

As you can see, there's "NoSuchBeanDefinitionException", saying there's not a single bean which qualifies as autowire candidate.

Just annotate your CompanyReadRepositoryTest with @Component(or any bean definition annotation) and it's gonna be OK.

In your case, the best annotation is @Repository.

See what's the difference between @Repository and the other bean definition annotations.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM