我想解决的一般问题是这个。我有一个解决方案,但它非常笨重,而且我希望有人知道一个更有序的解决方案。
Dropwizard提供了一个名为DropwizardAppRule的JUnit TestRule,用于集成测试。你这样使用它:
@ClassRule
public static final DropWizardAppRule<MyConfiguration> APP_RULE = new DropwizardAppRule(MyApplication.class, myYmlResourceFilePath, ConfigOverride("mydatabase.url", myJdbcUrl));
它将启动您的应用程序,使用您的yml资源文件配置它,并使用您在构造函数中指定的替代。但请注意,您的覆盖在施工时受到约束。
还有JUnit规则来启动Docker容器,我使用一个来启动MySql,还有一个JUnit RuleChain来强制在启动Dropwizard应用程序之前容器必须启动的事实这取决于它。
如果我愿意事先指定希望MySql容器公开的端口,那么这一切都很有效。我不是。我希望这些集成测试能够在构建机器上运行,很可能并行地用于同一项目的分支构建,我更倾向于使用您要求Docker选择任何可用端口的机制,并使用它。
我遇到的问题是,在构建DropwizardAppRule时,暴露的容器端口是未知的,这是唯一可以绑定配置覆盖的时间。
我采用的解决方案是制作包装器JUnit Rule,如下所示:
public class CreateWhenRunRuleWrapper<T extends ExternalResource> extends ExternalResource {
private final Supplier<T> wrappedRuleFactory;
private T wrappedRule;
public CreateWhenRunRuleWrapper(Supplier<T> wrappedRuleFactory) {
this.wrappedRuleFactory = wrappedRuleFactory;
}
public T getWrappedRule() {
return wrappedRule;
}
@Override
protected void before() throws Throwable {
wrappedRule = wrappedRuleFactory.get();
wrappedRule.before();
}
@Override
protected void after() {
wrappedRule.after();
}
}
这很有用,允许我在before()方法中构造DropWizardAppRule类,但显然不在JUnit的设计意图之内,因为我必须在org.junit中找到它。规则包,以使我的类能够调用后期创建的规则的before()和after()方法。
实现同一目标的更有条理,最佳实践方式是什么?
答案 0 :(得分:0)
我们提出的2个选项:
hacky解决方案是使用static {},它在启动容器之后但在初始化dropwizard实例之前执行代码:
public static final GenericContainer mongodb = new GenericContainer("mongo:latest").withExposedPorts(27017);
static {
mongodb.start();
System.setProperty("dw.mongoConfig.uri", "mongodb://" + mongodb.getContainerIpAddress() + ":" + mongodb.getMappedPort(27017));
}
@ClassRule
public static final DropwizardIntegrationAppRule<Config> app1 = new DropwizardIntegrationAppRule<>(Service.class);
第二种选择更清洁,更像你的选择。
private static final MongoDContainerRule mongo = new MongoDContainerRule();
private static final DropwizardIntegrationAppRule<Config> app = new DropwizardIntegrationAppRule<>(Service.class);
@ClassRule
public static final RuleChain chain = RuleChain
.outerRule(mongo)
.around(app)
MongoDContainerRule就像你的包装器,但它也通过系统属性设置了正确的端口。
public class MongoDContainerRule extends MongoDBContainerBase {
private static final GenericContainer mongodb = new GenericContainer("mongo:latest").withExposedPorts(27017);
@Override
protected void before() throws Throwable {
mongodb.start();
System.setProperty("dw.mongoConfig.uri", "mongodb://" + mongodb.getContainerIpAddress() + ":" + mongodb.getMappedPort(27017));
System.setProperty("dw.mongoConfig.tls", "false");
System.setProperty("dw.mongoConfig.dbName", DB_NAME);
}
@Override
protected void after() {
mongodb.stop();
}
}
容器会在自由端口上暴露mongodb。 mongodb.getMappedPort(internalPort)将返回它。 System.setProperty(“dw。*”)将值注入dropwizard配置。