首页 > 解决方案 > 测试 MongoDB 存储库:使用名称创建 bean 时出错:没有符合条件的 bean 类型

问题描述

问题

运行mvn test在 Mongo 存储库的单元测试中返回以下错误:

创建名称为“my_package.infrastructure.mongo.repositories.UserRepositoryMongoImplTests”的 bean 时出错:通过字段“userRepository”表示的依赖关系不满足;嵌套异常是 org.springframework.beans.factory.NoSuchBeanDefinitionException:没有可用的“my_package.infrastructure.mongo.repositories.users.UserRepositoryMongoImpl”类型的合格 bean

正如您在下面的代码中看到的那样,我确保将@Repository注释添加到我的实现类(AKA UserRepositoryMongoImpl)中,我也尝试了@Component注释,但它不起作用。然后我尝试将@ComponentScan("my_package")注释添加到我的配置类中,但仍然没有成功。

代码

我正在使用Java 11,Spring Boot和. 我的文件夹结构如下:JUnitTestContainers

.
├── src/
│   ├── main/
│   │   └── java/
│   │       └── my_package/
│   │           ├── domain/
│   │           │   └── users/
│   │           │       ├── User.java
│   │           │       └── UserRepository.java
│   │           ├── infrastructure/
│   │           │   └── mongo/
│   │           │       └── repositories/
│   │           │           └── UserRepositoryMongoImpl.java
│   │           └── ApplicationConfig.java
│   └── test/
│       └── my_package/
│           └── infrastructure/
│               └── mongo/
│                   └── repositories/
│                       └── UserRepositoryMongoImplTests.java
└── pom.xml

用户存储库.java

public interface UserRepository {
    public User findByUsername(String username);
    public User save(User user);
    public void delete(User user);
}

ApplicationConfig.java

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("my_package")
public class ApplicationConfig {
}

UserRepositoryMongoImpl.java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Repository;

import my_package.domain.users.User;
import my_package.domain.users.UserRepository;

@Repository
public class UserRepositoryMongoImpl implements UserRepository {
    @Autowired
    private MongoTemplate mongoTemplate;

    private static final String COLLECTION_NAME = "users";

    @Override
    public User findByUsername(String username) {
        return mongoTemplate.findOne(Query.query(Criteria.where("username").is(username)), User.class, COLLECTION_NAME);
    }

    @Override
    public User save(User user) {
        return mongoTemplate.save(user, COLLECTION_NAME);
    }

    @Override
    public void delete(User user) {
        mongoTemplate.remove(user, COLLECTION_NAME);
    }
}

UserRepositoryMongoImplTests.java

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
import org.testcontainers.containers.MongoDBContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.utility.DockerImageName;

import my_package.domain.users.User;
import my_package.infrastructure.mongo.repositories.users.UserRepositoryMongoImpl;

@Testcontainers
@DataMongoTest(excludeAutoConfiguration = {
    EmbeddedDataSourceConfiguration.class
})
public class UserRepositoryMongoImplTests {
    @Autowired
    private UserRepositoryMongoImpl userRepository;

    @Container
    private MongoDBContainer mongoDBContainer = new MongoDBContainer(DockerImageName.parse("mongo:4.4.4"));

    @BeforeEach
    void mongoDbContainerStarting() {
        mongoDBContainer.start();
        System.setProperty("spring.data.mongodb.uri", mongoDBContainer.getReplicaSetUrl());
    }

    @AfterEach
    void mongoDbContainerStoping() {
        mongoDBContainer.stop();
    }

    @Test
    public void shouldSaveValidNewUser() {
        User user = new User("username123", "heuehueheuh");
        user = userRepository.save(user);

        assert(user.id() != null);
        assert(user.username().equals("username123"));
        assert(user.password().equals("heuehueheuh"));
    }
}

最后: 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 https://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.4.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>br.nom.carneiro.carlos</groupId>
    <artifactId>future_software_003-ws</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>my-project</name>
    <description>Random description</description>
    <properties>
        <java.version>11</java.version>
        <testcontainers.version>1.15.2</testcontainers.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>
        <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.restdocs</groupId>
            <artifactId>spring-restdocs-mockmvc</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.testcontainers</groupId>
            <artifactId>mongodb</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.testcontainers</groupId>
            <artifactId>junit-jupiter</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.assertj</groupId>
            <artifactId>assertj-guava</artifactId>
            <version>3.4.0</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.testcontainers</groupId>
                <artifactId>testcontainers-bom</artifactId>
                <version>${testcontainers.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.asciidoctor</groupId>
                <artifactId>asciidoctor-maven-plugin</artifactId>
                <version>1.5.8</version>
                <executions>
                    <execution>
                        <id>generate-docs</id>
                        <phase>prepare-package</phase>
                        <goals>
                            <goal>process-asciidoc</goal>
                        </goals>
                        <configuration>
                            <backend>html</backend>
                            <doctype>book</doctype>
                        </configuration>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>org.springframework.restdocs</groupId>
                        <artifactId>spring-restdocs-asciidoctor</artifactId>
                        <version>${spring-restdocs.version}</version>
                    </dependency>
                </dependencies>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

我之前查过的问题

如果你能给我建议,任何意见将不胜感激。

编辑

我尝试手动创建 Bean,将以下代码添加到我的配置类中:

    @Bean
    public UserRepositoryMongoImpl userRepositoryMongoImpl() {
        return new UserRepositoryMongoImpl();
    }

然后我收到以下错误:

无法注册在类路径资源 [blablabla] 中定义的 bean 'userRepositoryMongoImpl'。已在文件 [blablabla] 中定义了具有该名称的 bean,并且禁用了覆盖。

这可能意味着通过注解正确声明了 bean @Repository,但由于某种原因,Spring 没有发现它可以注入我的测试类。

标签: javaspring-boot

解决方案


我解决了在@SpringBootApplication课堂上添加以下注释的问题@ComponentScan(basePackages = {"my_package.infrastructure.mongo"}):原来我的 ComponentScan 注释是错误的并且在错误的类中。

我在阅读 NoSuchBeanDefinitionException 问题的答案时得出了这个结论:no qualifying bean of type


推荐阅读