我有一个关于喷射玻璃的简单项目。这是您使用 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);
}
}
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
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
我不知道为什么无法建立连接。也许有人对如何在这种情况下设置集成测试有想法?
删除了依赖项“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);
}