简体   繁体   English

单元测试垂直部署

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM