创建类路径资源中定义的名称为“connectionFactory”的bean时出错[org/springframework/boot/autoconfigure/r2dbc/

问题描述 投票:0回答:1

我有一个关于喷射玻璃的简单项目。这是您使用 MongoDB 的地方,它配置为 ReplicaSet。我没有使用自动配置,而是使用配置文件来配置Mongo的运行。

@Configuration
@RequiredArgsConstructor
@EnableConfigurationProperties(MongoProperties.class)
@EnableReactiveMongoRepositories(basePackages = "com.example.demo.repository")
public class MongoConfig extends AbstractReactiveMongoConfiguration {

    private final MongoProperties mongoProperties;

    @Override
    protected String getDatabaseName() {
        return mongoProperties.getDatabase();
    }

    @Override
    public com.mongodb.reactivestreams.client.MongoClient reactiveMongoClient() {

        String mongoUri = mongoProperties.getUri();

        return com.mongodb.reactivestreams.client.MongoClients.create(mongoUri);
    }

    @Bean
    public ReactiveMongoTemplate reactiveMongoTemplate() {
        return new ReactiveMongoTemplate(reactiveMongoClient(), getDatabaseName());
    }

    @Bean
    public ReactiveMongoTransactionManager transactionManager(ReactiveMongoDatabaseFactory factory) {
        return new ReactiveMongoTransactionManager(factory);
    }
}

spring:
  autoconfigure:
    exclude:
      - org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration
  data:
    mongodb:
      host: localhost
      port: 27017
      database: accounts
      username: root
      password: root
      authentication-database: admin
      auto-index-creation: true
      replica-set-name: rs0
      uri: mongodb://${spring.data.mongodb.username}:${spring.data.mongodb.password}@localhost:27017/${spring.data.mongodb.database}?authSource=${spring.data.mongodb.authentication-database}
server:
  port: 9080

logging:
  level:
    org.springframework.data.mongodb.core.MongoTemplate: DEBUG
    org.mongodb.driver: DEBUG
    org:
      springframework:
        data:
          mongodb:
            core:
              MongoTemplate: DEBUG
              ReactiveMongoTemplate: DEBUG
      mongodb:
        driver:
          protocol:
            command: DEBUG

    com:
      mongodb:
        driver: DEBUG # Включить логирование для MongoDB драйвера

应用程序按预期运行。

但是,我决定编写集成测试来测试应用程序的操作。

@TestConfiguration
@Import(MongoConfig.class)
public class TestMongoConfig {
    @Bean
    @Primary
    public MongoProperties mongoProperties() {
        MongoProperties properties = new MongoProperties();
        properties.setUri(mongoDBContainer.getReplicaSetUrl());
        properties.setDatabase("test");
        return properties;
    }

}
@ActiveProfiles("test")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
        classes = DemoApplication.class)

@Testcontainers
@AutoConfigureWebTestClient
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@Import(TestMongoConfig.class)
@TestPropertySource(properties=
        {"spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration"})
class AccountControllerIntegrationTest {


    @Autowired
    private WebTestClient webTestClient;

    @Autowired
    private AccountRepository accountRepository;

    @Container
    static MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:4.4.2")
            .withCommand("--replSet", "rs0")
            .withExposedPorts(27017);


    @DynamicPropertySource
    static void setProperties(DynamicPropertyRegistry registry) {
        mongoDBContainer.start();
        String replicaSetUrl = mongoDBContainer.getReplicaSetUrl();
        String username = "yourUsername";  
        String password = "yourPassword";
        String database = "test"; 
        String authSource = "admin"; 

        String formattedUri = String.format("mongodb://%s:%s@%s/%s?authSource=%s",
                username,
                password,
                replicaSetUrl.split("://")[1].split("/")[0], 
                database,
                authSource);

        registry.add("spring.data.mongodb.uri", () -> formattedUri);
        registry.add("spring.data.mongodb.database", () -> database);
    }

    @BeforeAll
    static void initReplicaSet() {

        mongoDBContainer.start();

        MongoClient mongoClient = MongoClients.create(mongoDBContainer.getReplicaSetUrl());
        MongoDatabase admin = mongoClient.getDatabase("admin");
        Document config = new Document("_id", "rs0")
                .append("members", Collections.singletonList(
                        new Document("_id", 0)
                                .append("host", "localhost:" + mongoDBContainer.getMappedPort(27017))
                ));
        admin.runCommand(new Document("replSetInitiate", config));
        mongoClient.close();
    }

    @BeforeEach
    void setUp() {
        accountRepository.deleteAll().block();
    }

    @Test
    void testCreateAccount() {
        AccountDto accountDto = new AccountDto(null, "John Doe", 30);

        webTestClient.post().uri("/accounts")
                .contentType(MediaType.valueOf("application/json-patch+json"))
                .body(Mono.just(accountDto), AccountDto.class)
                .exchange()
                .expectStatus().isOk()
                .expectBody()
                .jsonPath("$.id").isNotEmpty()
                .jsonPath("$.firstName").isEqualTo("John Doe")
                .jsonPath("$.age").isEqualTo(30);
    }
}
  • 应用程序测试.yml
spring:
  data:
    mongodb:
      auto-index-creation: true
  autoconfigure:
    exclude:
      - org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration

logging:
  level:
    org.springframework.data.mongodb: DEBUG
    org.testcontainers: DEBUG
  • 构建.gradle

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.3.4'
    id 'io.spring.dependency-management' version '1.1.6'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(17)
    }
}
....

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-actuator'
    implementation 'org.springframework.boot:spring-boot-starter-validation'
    implementation 'org.springframework.boot:spring-boot-starter-data-mongodb-reactive'
    implementation 'org.springframework.boot:spring-boot-starter-webflux'
    //implementation 'io.micrometer:micrometer-tracing-bridge-brave'
    compileOnly 'org.projectlombok:lombok'
    //runtimeOnly 'io.micrometer:micrometer-registry-prometheus'
    annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'org.springframework.boot:spring-boot-testcontainers'
    testImplementation 'io.projectreactor:reactor-test'
    testImplementation 'org.testcontainers:junit-jupiter'
    testImplementation 'org.testcontainers:mongodb'
    implementation 'org.testcontainers:r2dbc'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
....

在类路径资源[org/springframework/boot/autoconfigure/r2dbc/ConnectionFactoryConfigurations$GenericConfiguration.class]中创建名称为“connectionFactory”的bean时出错:无法实例化[io.r2dbc.spi.ConnectionFactory]:工厂方法“connectionFactory”抛出异常并显示消息:无法确定合适的 R2DBC 连接 URL

我不知道为什么无法建立连接。也许有人对如何在这种情况下设置集成测试有想法?

spring-webflux junit5 testcontainers spring-data-r2dbc
1个回答
0
投票

删除了依赖项“org.testcontainers:r2dbc”

稍微改变了测试的配置

@ActiveProfiles("test")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
        classes = DemoApplication.class)

@Testcontainers
@AutoConfigureWebTestClient
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@Import(TestMongoConfig.class)
class AccountControllerIntegrationTest {


    @Autowired
    private WebTestClient webTestClient;

    @Autowired
    private AccountRepository accountRepository;

    @Container
    static MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:4.4.2")
            .withCommand("--replSet", "rs0")
            .withExposedPorts(27017);

    static{
        mongoDBContainer.start();
    }


    @DynamicPropertySource
    static void setProperties(DynamicPropertyRegistry registry) {

        String replicaSetUrl = mongoDBContainer.getReplicaSetUrl();
        System.out.println("MongoDB URL: " + replicaSetUrl);

        String username;
        String password;

        String[] parts = replicaSetUrl.split("@");
        if (parts.length > 1) {
            String credentials = parts[0].split("://")[1];
            String[] userPass = credentials.split(":");
            if (userPass.length == 2) {

                username = userPass[0];
                password = userPass[1];
                System.out.println("Username: " + userPass[0]);
                System.out.println("Password: " + userPass[1]);
            }
        }


        registry.add("spring.data.mongodb.uri", mongoDBContainer::getReplicaSetUrl);
    }


    @BeforeEach
    void setUp() {
        accountRepository.deleteAll().block();
    }

    @Test
    void testCreateAccount() {
        AccountDto accountDto = new AccountDto(null, "John Doe", 30);

        webTestClient.post().uri("/accounts")
                .contentType(MediaType.valueOf("application/json-patch+json"))
                .body(Mono.just(accountDto), AccountDto.class)
                .exchange()
                .expectStatus().isOk()
                .expectBody()
                .jsonPath("$.id").isNotEmpty()
                .jsonPath("$.firstName").isEqualTo("John Doe")
                .jsonPath("$.age").isEqualTo(30);
    }

    @Test
    void testFindById() {
        Account account = accountRepository.save(new Account(null, "Jane Doe", 25)).block();

        webTestClient.get().uri("/accounts/{id}", account.getId())
                .exchange()
                .expectStatus().isOk()
                .expectBody()
                .jsonPath("$.id").isEqualTo(account.getId())
                .jsonPath("$.firstName").isEqualTo("Jane Doe")
                .jsonPath("$.age").isEqualTo(25);
    }
© www.soinside.com 2019 - 2024. All rights reserved.