使用 Junit 5 和 Micronaut 设置测试 MongoDBContainer
Setting Test MongoDBContainer with Junit 5 and Micronaut
尝试使用 Junit 5 和 micronaut 设置测试 MongoDBContainer,而不是使用 application.yml 配置在测试环境的随机端口上启动 MongoDB。
application.yml
micronaut:
application:
name: feteBirdProductConsumer
mongodb:
uri: "mongodb://${MONGO_HOST:localhost}:${MONGO_PORT:27017}"
database: "FeteBird-Product"
Junit测试
@MicronautTest
@Testcontainers
public class ProductListenerTest {
private final IProductProducer iProductProducer;
@Container
private final MongoDBContainer mongoDBContainer = new MongoDBContainer(DockerImageName.parse("mongo:4.0.10"));
public ProductListenerTest(IProductProducer iProductProducer) {
this.iProductProducer = iProductProducer;
}
@BeforeEach
@DisplayName("Mongo Db container starting")
void mongoDbContainerStarting() {
mongoDBContainer.start();
}
@Test
@DisplayName("Check if Mongo db container is up")
void checkIfMongoDbContainerIsUp() {
Assertions.assertTrue(mongoDBContainer.isRunning());
}
@Test
@DisplayName("Should search based on the name")
void shouldSearchBasedOnTheName() {
iProductProducer.findFreeText("string").subscribe(item -> {
System.out.println(item);
});
}
}
在 shouldSearchBasedOnTheName
方法中,return 值来自 application.yml MongoDB 配置。
在测试环境中,我没有向 MongoDB 插入任何值,但是该方法 return 从应用程序 MongoDB
中获取了值
我想我缺少 mongoDb 的配置,但不太确定如何设置
更新
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class ProductListenerTest implements TestPropertyProvider {
@Nonnull
@Override
public Map<String, String> getProperties() {
mongoDBContainer.start();
String address = mongoDBContainer.getHost();
Integer port = mongoDBContainer.getFirstMappedPort();
return CollectionUtils.mapOf(
"MONGO_HOST", address,
"MONGO_PORT", port
);
}
}
异常
com.mongodb.MongoSocketReadException: Prematurely reached end of stream
您启动的测试容器绑定了一个随机端口,您需要手动将其提供给 Micronaut,两者之间没有自动集成。我不认为你可以使用 @MicronautTest
来解决这个问题,因为它甚至在容器初始化之前就运行了应用程序上下文。但是您仍然可以自己配置和启动上下文:
@Testcontainers
public class ProductListenerTest {
@Container
private MongoDBContainer mongoDBContainer =
new MongoDBContainer(DockerImageName.parse("mongo:4.0.10"));
private ApplicationContext context;
private MongoClient client;
@BeforeEach
void mongoDbContainerStarting() {
mongoDBContainer.start();
// Overwrite the mongodb.uri value from your configuration file
context = ApplicationContext.run(
Map.of("mongodb.uri", mongoDBContainer.getReplicaSetUrl()));
client = context.getBean(MongoClient.class);
}
Micronaut 需要从 MongoDBContainer 获取连接 URL,因此使用 MicronautTest 不会像使用特殊“tc”数据库的 SQL 容器那样工作 URLs。 JUnit 答案类似于我对 Spock 使用的答案,
@Testcontainers
class MongoControllerSpec extends Specification {
@Shared
MongoDBContainer mongo = new MongoDBContainer("mongo:4.1.1")
.withExposedPorts(27017)
@Shared
@AutoCleanup
EmbeddedServer embeddedServer
@Shared
@AutoCleanup
RxHttpClient rxClient
def setupSpec() {
embeddedServer = ApplicationContext.run(EmbeddedServer,
['mongodb.uri': mongo.getReplicaSetUrl("micronaut")])
rxClient = embeddedServer.applicationContext.createBean(RxHttpClient, embeddedServer.getURL())
}
...
}
尝试使用 Junit 5 和 micronaut 设置测试 MongoDBContainer,而不是使用 application.yml 配置在测试环境的随机端口上启动 MongoDB。
application.yml
micronaut:
application:
name: feteBirdProductConsumer
mongodb:
uri: "mongodb://${MONGO_HOST:localhost}:${MONGO_PORT:27017}"
database: "FeteBird-Product"
Junit测试
@MicronautTest
@Testcontainers
public class ProductListenerTest {
private final IProductProducer iProductProducer;
@Container
private final MongoDBContainer mongoDBContainer = new MongoDBContainer(DockerImageName.parse("mongo:4.0.10"));
public ProductListenerTest(IProductProducer iProductProducer) {
this.iProductProducer = iProductProducer;
}
@BeforeEach
@DisplayName("Mongo Db container starting")
void mongoDbContainerStarting() {
mongoDBContainer.start();
}
@Test
@DisplayName("Check if Mongo db container is up")
void checkIfMongoDbContainerIsUp() {
Assertions.assertTrue(mongoDBContainer.isRunning());
}
@Test
@DisplayName("Should search based on the name")
void shouldSearchBasedOnTheName() {
iProductProducer.findFreeText("string").subscribe(item -> {
System.out.println(item);
});
}
}
在 shouldSearchBasedOnTheName
方法中,return 值来自 application.yml MongoDB 配置。
在测试环境中,我没有向 MongoDB 插入任何值,但是该方法 return 从应用程序 MongoDB
中获取了值我想我缺少 mongoDb 的配置,但不太确定如何设置
更新
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class ProductListenerTest implements TestPropertyProvider {
@Nonnull
@Override
public Map<String, String> getProperties() {
mongoDBContainer.start();
String address = mongoDBContainer.getHost();
Integer port = mongoDBContainer.getFirstMappedPort();
return CollectionUtils.mapOf(
"MONGO_HOST", address,
"MONGO_PORT", port
);
}
}
异常
com.mongodb.MongoSocketReadException: Prematurely reached end of stream
您启动的测试容器绑定了一个随机端口,您需要手动将其提供给 Micronaut,两者之间没有自动集成。我不认为你可以使用 @MicronautTest
来解决这个问题,因为它甚至在容器初始化之前就运行了应用程序上下文。但是您仍然可以自己配置和启动上下文:
@Testcontainers
public class ProductListenerTest {
@Container
private MongoDBContainer mongoDBContainer =
new MongoDBContainer(DockerImageName.parse("mongo:4.0.10"));
private ApplicationContext context;
private MongoClient client;
@BeforeEach
void mongoDbContainerStarting() {
mongoDBContainer.start();
// Overwrite the mongodb.uri value from your configuration file
context = ApplicationContext.run(
Map.of("mongodb.uri", mongoDBContainer.getReplicaSetUrl()));
client = context.getBean(MongoClient.class);
}
Micronaut 需要从 MongoDBContainer 获取连接 URL,因此使用 MicronautTest 不会像使用特殊“tc”数据库的 SQL 容器那样工作 URLs。 JUnit 答案类似于我对 Spock 使用的答案,
@Testcontainers
class MongoControllerSpec extends Specification {
@Shared
MongoDBContainer mongo = new MongoDBContainer("mongo:4.1.1")
.withExposedPorts(27017)
@Shared
@AutoCleanup
EmbeddedServer embeddedServer
@Shared
@AutoCleanup
RxHttpClient rxClient
def setupSpec() {
embeddedServer = ApplicationContext.run(EmbeddedServer,
['mongodb.uri': mongo.getReplicaSetUrl("micronaut")])
rxClient = embeddedServer.applicationContext.createBean(RxHttpClient, embeddedServer.getURL())
}
...
}