java - Spring boot Autowired 存储库不适用于 SpringRunner 和 JPA 数据

标签 java spring spring-boot junit spring-data-jpa

当我尝试运行我的测试时,出现以下错误。我是 spring boot 的新手,所以无法理解确切的问题。

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'api.usecase.createtask.CreateTaskTest': Unsatisfied dependency expressed through field 'taskRepository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'api.usecase.createtask.repository.CreateTaskRepository' 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(AutowiredAnnotationBeanPostProcessor.java:588)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:386)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:118)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'api.usecase.createtask.repository.CreateTaskRepository' 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.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1486)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
    ... 27 more

我的单元测试

package api.usecase.createtask;

import api.model.Task;
import api.usecase.createtask.contracts.CreateTaskRequest;
import api.usecase.createtask.contracts.CreateTaskResponse;
import api.usecase.createtask.repository.CreateTaskRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.List;

@RunWith(SpringRunner.class)
public class CreateTaskTest {

    @Autowired
    private CreateTaskRepository taskRepository;

    @Test
    public void createSuccessfulTask() {
        CreateTaskRequest createTaskRequest = new CreateTaskRequest();
        createTaskRequest.setDescription("Wash car");
        createTaskRequest.setAmount(10);
        createTaskRequest.setRecurrenceType("ONE_OFF");
        createTaskRequest.setStatus("NOT_COMPLETED");
        CreateTaskResponse createTaskResponse = new CreateTaskResponse();
        CreateTask createTask = new CreateTask(this.taskRepository);
        createTask.handle(createTaskRequest, createTaskResponse);
        List<Task> tasks = this.taskRepository.findAll();
        tasks.forEach(System.out::println);
    }
}

我的存储库类

package api.usecase.createtask.repository;


import api.model.Task;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface CreateTaskRepository extends JpaRepository <Task, Long>{
    List<Task> findAll();
}

主应用程序文件。我也尝试使用 @EnableJpaRepositories(basePackages = {"api.usecase.createtask.repository"}, considerNestedRepositories = true) 选项但仍然无法正常工作。

package api;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

创建任务逻辑类

package api.usecase.createtask;

import api.model.Task;
import api.usecase.createtask.contracts.CreateTaskRequest;
import api.usecase.createtask.contracts.CreateTaskResponse;
import api.usecase.createtask.repository.CreateTaskRepository;


public class CreateTask {
    private CreateTaskRepository repository;

    public CreateTask(CreateTaskRepository repository) {
        this.repository = repository;
    }

    public void handle(CreateTaskRequest createTaskRequest, CreateTaskResponse createTaskResponse) {
        Task task = new Task(
                createTaskRequest.getDescription(),
                createTaskRequest.getAmount(),
                createTaskRequest.getRecurrenceType(),
                createTaskRequest.getStatus()
        );
        this.repository.save(task);
    }
}

模型

package api.model;

import org.springframework.stereotype.Component;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "CHILD_Tasks")
public class Task {
    @Id
    @Column(name = "id")
    private long id;

    @Column(name = "description")
    private String description;

    @Column(name = "amount")
    private float amount;

    @Column(name = "recurrenceType")
    private String recurrenceType;

    @Column(name = "status")
    private String status;

    public Task(String description, Float amount, String recurrenceType, String status) {
        this.description = description;
        this.amount = amount;
        this.recurrenceType = recurrenceType;
        this.status = status;
    }

    public void setId(long id) {
        this.id = id;
    }

    public long getId() {
        return this.id;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getDescription() {
        return this.description;
    }

    public void setAmount(float amount) {
        this.amount = amount;
    }

    public float getAmount() {
        return this.amount;
    }

    public void setRecurrenceType(String recurrenceType) {
        this.recurrenceType = recurrenceType;
    }

    public String getRecurrenceType() {
        return this.recurrenceType;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public String getStatus() {
        return this.status;
    }
}

目录结构

enter image description here

应用程序属性文件

spring.datasource.url=jdbc:mysql://localhost/tasks_db
spring.datasource.username=root
spring.datasource.password=root

spring.jpa.hibernate.ddl-auto=none
spring.jpa.show-sql = true
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect

spring.h2.console.enabled=true
spring.h2.console.path=/console
spring.h2.console.settings.trace=false
spring.h2.console.settings.web-allow-others=false

Maven 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>

    <groupId>com.example</groupId>
    <artifactId>api</artifactId>
    <version>2.0</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.2.RELEASE</version>
    </parent>

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

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

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

        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.7.0</version>
        </dependency>

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

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-java</artifactId>
            <version>${cucumber.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-spring</artifactId>
            <version>${cucumber.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-junit</artifactId>
            <version>${cucumber.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>1.4.194</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>5.2.9.Final</version>
        </dependency>

    </dependencies>

    <properties>
        <java.version>1.8</java.version>
        <cucumber.version>1.2.5</cucumber.version>
    </properties>

    <distributionManagement>
        <snapshotRepository>
            <id>snapshots</id>
            <url>http://0.0.0.0:8081/nexus/content/repositories/snapshots</url>
        </snapshotRepository>
        <repository>
            <id>releases</id>
            <url>http://0.0.0.0:8081/nexus/content/repositories/releases</url>
        </repository>
    </distributionManagement>


    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-deploy-plugin</artifactId>
                <configuration>
                    <skip>true</skip>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.sonatype.plugins</groupId>
                <artifactId>nexus-staging-maven-plugin</artifactId>
                <version>1.6.3</version>
                <executions>
                    <execution>
                        <id>default-deploy</id>
                        <phase>deploy</phase>
                        <goals>
                            <goal>deploy</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <serverId>nexus</serverId>
                    <nexusUrl>http://0.0.0.0:8081/nexus/</nexusUrl>
                    <skipStaging>true</skipStaging>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

最佳答案

您还没有指定您的 Spring 配置。 Spring 不知道您有什么 bean 或在哪里可以找到它们。

如果您只想测试存储库,则需要添加 DataJpaTest 注释。文档:http://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/test/autoconfigure/orm/jpa/DataJpaTest.html

@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase(connection = EmbeddedDatabaseConnection.H2)
public class CreateTaskTest {
...

By default it will configure an in-memory embedded database, scan for @Entity classes and configure Spring Data JPA repositories. Regular @Component beans will not be loaded into the ApplicationContext.

Data JPA tests are transactional and rollback at the end of each test by default [...]

Data JPA tests may also inject a TestEntityManager bean which provides an alternative to the standard JPA EntityManager specifically designed for tests. If you want to use TestEntityManager outside of @DataJpaTests you can also use the @AutoConfigureTestEntityManager annotation. [...]

@RunWith(SpringRunner.class) @DataJpaTest public class ExampleRepositoryTests {

    @Autowired
    private TestEntityManager entityManager;

    @Autowired
    private UserRepository repository;

    @Test
    public void testExample() throws Exception {
        this.entityManager.persist(new User("sboot", "1234"));
        User user = this.repository.findByUsername("sboot");
        assertThat(user.getUsername()).isEqualTo("sboot");
        assertThat(user.getVin()).isEqualTo("1234");
    } }

此外,如果您需要从所有组件创建 bean,您可以使用 SpringBootTest

我建议您阅读 Spring Boot 测试引用 (link)。 Spring 有非常好的文档。

关于java - Spring boot Autowired 存储库不适用于 SpringRunner 和 JPA 数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44498044/

相关文章:

spring-boot - Kotlin Spring Boot Webflux 使用 @Valid 注解验证 @RequestBody

java - 在 J2ME 中通过 http 发送和接收数据以及处理菜单和屏幕

java - 通过 Spring 创建的 H2 服务器数据库无法访问

java - 吉斯 "Throwing Providers": How to bind to a type with generics?

java - Spring无法 Autowiring 类

java - 无法在测试中反射性地更改 Spring Controller 内的字段

spring-boot - Spring Boot和Spring Data JPA中的事务管理

java - 如何运行gulp任务和spring-boot :run together with maven?

java - 向一个 JFrame 添加多种类型的背景

java - 将图标设置为 JFrame