[英]Unit testing a verticle deployment
I have a simple Verticle that reads configuration from a properties file and loads in into vertx config. 我有一个简单的Verticle,它从属性文件中读取配置并将其加载到vertx config中。 I have written a unit test to test the deployment of this verticle and possible cause of test failure is non availability of the properties file at the location.
我已经编写了单元测试来测试此verticle的部署,并且测试失败的可能原因是该位置的属性文件不可用。
When I run the test, unit test passes irrespective of whether I change the properties file name or path and the handler says the verticle was deployed successfully. 在运行测试时,无论是否更改属性文件名或路径,单元测试都会通过,并且处理程序会说该顶点已成功部署。
Am I doing something wrong here? 我在这里做错什么了吗? Below is my code
下面是我的代码
import io.vertx.config.ConfigRetrieverOptions;
import io.vertx.config.ConfigStoreOptions;
import io.vertx.core.DeploymentOptions;
import io.vertx.core.json.JsonObject;
import io.vertx.rxjava.config.ConfigRetriever;
import io.vertx.rxjava.core.AbstractVerticle;
/**
* This is the main launcher verticle, the following operations will be executed in start() method of this verticle:
* 1. Read configurations from application.properties file
* 2. Deploy all other verticles in the application
*/
public class LauncherVerticle extends AbstractVerticle {
@Override
public void start() throws Exception {
//set up configuration from the properties file
ConfigStoreOptions fileStore = new ConfigStoreOptions()
.setType("file")
.setFormat("properties")
.setConfig(new JsonObject().put("path", System.getProperty("vertex.config.path"));
//create config retriever options add properties to filestore
ConfigRetrieverOptions options = new ConfigRetrieverOptions().addStore(fileStore);
ConfigRetriever configRetriever = ConfigRetriever.create(vertx, options);
DeploymentOptions deploymentOptions = new DeploymentOptions();
//Deploy verticles after the config has been loaded
//The configurations are loaded into JsonConfig object
//This JsonConfig object can be accessed in other verticles using the config() method.
configRetriever.rxGetConfig().subscribe(s -> {
//pass on the JsonConfig object to other verticles through deployment options
deploymentOptions.setConfig(s);
vertx.deployVerticle(AnotherVerticle.class.getName(), deploymentOptions);
}, e -> {
log.error("Failed to start application : " + e.getMessage(), e);
try {
stop();
} catch (Exception e1) {
log.error("Unable to stop vertx, terminate the process manually : "+e1.getMessage(), e1);
}
});
}
}
This is my unit test 这是我的单元测试
import io.vertx.ext.unit.TestContext;
import io.vertx.ext.unit.junit.VertxUnitRunner;
import io.vertx.rxjava.core.Vertx;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import rx.Single;
@RunWith(VertxUnitRunner.class)
public class LoadConfigurationTest {
/**
* Config should be loaded successfully
*
* @param context
*/
@Test
public void loadConfigTest(TestContext context) {
/*
* Set the system property "vertx.config.path" with value "application.properties"
* This system property will be used in the Launcher verticle to read the config file
*/
System.setProperty("vertx.config.path", "/opt/vertx/config/application.properties");
//create vertx instance
Vertx vertx = Vertx.vertx();
Single<String> single = vertx.rxDeployVerticle(LauncherVerticle.class.getName());
single.subscribe(s -> {
vertx.rxUndeploy(s);
}, e -> {
Assert.fail(e.getMessage());
});
}
/**
* Test for negative use case - file not available in the specified location
*
* @param context
*/
@Test
public void loadConfigFailTest(TestContext context) {
//set path = non existing path
System.setProperty("vertx.config.path", "/non/existing/path/application.properties");
//create vertx instance
Vertx vertx = Vertx.vertx();
Single single = vertx.rxDeployVerticle(LauncherVerticle.class.getName());
single.subscribe(s -> {
//not executing this statement
Assert.fail("Was expecting error but Verticle deployed successfully");
}, e -> {
//not executing this statement either
System.out.println("pass");
});
}
}
Can you try the below code inside your LauncherVerticle
the changes only include using AbstractVerticles
start
with Future
which is a neat way for handling the config loading and everything around the same during your starup. 您可以在
LauncherVerticle
尝试以下代码吗,所做的更改仅包括使用以Future
start
AbstractVerticles
,这是一种处理配置加载以及在启动过程中几乎所有操作的简洁方法。
public class LauncherVerticle extends AbstractVerticle {
@Override
public void start(Future<Void> startFuture) throws Exception {
ConfigStoreOptions fileStore = new ConfigStoreOptions()
.setType("file")
.setFormat("properties")
.setConfig(new JsonObject().put("path", System.getProperty("vertex.config.path")));
ConfigRetrieverOptions options = new ConfigRetrieverOptions().addStore(fileStore);
ConfigRetriever configRetriever = ConfigRetriever.create(vertx, options);
DeploymentOptions deploymentOptions = new DeploymentOptions();
configRetriever.rxGetConfig().subscribe(s -> {
deploymentOptions.setConfig(s);
vertx.deployVerticle(AnotherVerticle.class.getName(),
deploymentOptions,
result -> startFuture.complete()
);
},
startFuture::fail
);
}
}
startFuture
there, would help you to control the state of your verticle loading. startFuture
在那里,将帮助您控制startFuture
加载的状态。
Also remember that @Constantine way for handing the test is best way, use of Async
to prevent your tests passing without actually asserting anything. 还要记住,@ Constantine进行测试的方法是最好的方法,使用
Async
可以防止测试通过而无需实际声明任何内容。
Seems like there is nothing wrong with your verticle. 看来您的顶点没有问题。 However, there is something in tests - the asynchronous nature of verticle deployment is not taken into account.
但是,测试中存在某些问题-垂直部署的异步特性未考虑在内。 These test methods finish immediately instead of waiting for verticle deployment, and JUnit test that does not result in
AssertionError
is a passed test . 这些测试方法立即完成,而不是等待垂直部署,并且不会导致
AssertionError
JUnit测试是通过的测试 。 You have to signal completion explicitly using Async
. 您必须使用
Async
明确表示完成。
Please see an example for your negative scenario below: 请在下面查看您的负面情况示例:
import io.vertx.ext.unit.Async;
import io.vertx.ext.unit.TestContext;
import io.vertx.ext.unit.junit.RunTestOnContext;
import io.vertx.ext.unit.junit.VertxUnitRunner;
import io.vertx.rxjava.core.Vertx;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(VertxUnitRunner.class)
public class LoadConfigurationTest {
@Rule
public RunTestOnContext runTestOnContextRule = new RunTestOnContext();
@Test
public void testConfigLoading_shouldFail_whenConfigDoesNotExist(TestContext context) {
// create an Async instance that controls the completion of the test
Async async = context.async();
// set non existing path
System.setProperty("vertx.config.path", "/non/existing/path/application.properties");
// take vertx instance and wrap it with rx-ified version
Vertx vertx = Vertx.newInstance(runTestOnContextRule.vertx());
vertx.rxDeployVerticle(LauncherVerticle.class.getName()).subscribe(s -> {
context.fail("Was expecting error but Verticle deployed successfully"); // failure
}, e -> {
async.complete(); // success
});
}
}
Also please note that you can take a Vertx
instance from RunTestOnContext
rule (as in the snippet above). 另外请注意,您可以从
RunTestOnContext
规则中获取Vertx
实例(如上面的代码段所示)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.