2017-06-13 40 views
1

我有一個簡單的Verticle從配置文件中讀取配置並加載到vertx配置中。我已經寫了一個單元測試來測試這個Verticle的部署,並且測試失敗的可能原因是該位置的屬性文件不可用。單元測試垂直部署

當我運行測試時,單元測試通過,無論是否更改屬性文件名或路徑,處理程序說Verticle已成功部署。

我在這裏做錯了什麼?下面是我的代碼

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); 
      } 
     }); 
    } 
} 

這是我的單元測試

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"); 
     }); 
    } 
} 

回答

2

你可以盡你LauncherVerticle的變化中下面的代碼只能用AbstractVerticlesstartFuture這是您的Starup期間處理大約相同的配置加載和一切整潔的方式包括。

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那裏,會幫助你控制你的垂直加載狀態。

另外請記住@Constantine交付測試的方式是最好的方法,使用Async來防止測試通過而不實際聲明任何東西。

+0

謝謝,這對我有用。 – Rakesh

1

好像有什麼不對您的verticle。但是,測試中有一些東西 - 垂直部署的異步特性沒有考慮在內。這些測試方法立即結束,而不是等待垂直部署,並且不會導致AssertionError的JUnit測試爲通過測試。您必須使用Async明確表示完成。

請看一個例​​子下方的負面情景:

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 
     }); 
    } 
} 

同時請注意,你可以從RunTestOnContext規則採取Vertx實例(如上面的代碼段)。

+0

感謝君士坦丁,但使用'RunTestOnContext'中的vertx實例將不會給出vertx的rxified版本,這是我需要的。 – Rakesh

+0

很高興幫助。來自'RunTestOnContext'的'Vertx'實例確實沒有實現。這就是爲什麼我用'io.vertx.rxjava.core.Vertx.newInstance(runTestOnContextRule.vertx())'包裝它。然而,你可以簡單地在測試中使用非rxified版本,因爲rxified版本不是一個不同的實現,而只是'io.vertx.core.Vertx'功能的封裝。 – Constantine