4

我有 2 个使用 JUnit 实现的集成测试。这两个测试都执行对远程服务器的调用,并且服务器目标由环境变量配置:

System.setProperty("property", "value1");

棘手的是,对于 2 个测试,这些属性必须不同。如果我为每个单元测试设置环境变量,它就不起作用,因为我们使用的中间件在第一次调用时缓存了属性值并且不再评估它(对于第二次测试)。

我相信解决方案可能是在单独的进程中运行这些单元测试。我在这里看到了类似的讨论,但也许有更优雅的方式来使用 JUnit4 做到这一点?这个问题看起来很常见。或者也许还有另一种方法来运行具有不同配置的单元测试?

提前感谢您的任何建议。

4

5 回答 5

3

这取决于您如何运行 JUnit。

如果您希望能够从 IDE 或构建中运行它,请Runner使用 annotation 实现您的自定义和标记测试用例RunWith(MyRunner.class)

如果您使用的是 maven,并且您能够从那里运行测试<forkMode>always</forkMode>maven-surefire-plugin定义中就足够了。

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.11</version>
            <configuration>
                <systemProperties>
                    <systemProperty>
                        <name>panpwr.conf.dir</name>
                        <value>${basedir}/conf-test</value>
                    </systemProperty>
                </systemProperties>
                <forkMode>always</forkMode>

于 2012-09-03T10:20:16.853 回答
2

在测试之间无法重置状态被认为是不好的做法。虽然无法轻松测试的代码很常见,但解决方案并不简单。

即使您使用反射来执行此操作,我也会考虑重置缓存值。确切需要重置的内容取决于库的内部表示。

于 2012-09-03T10:14:26.137 回答
1

我需要在使用一些遗留代码的过程中隔离junit测试,所以我开发了小型maven插件Jute,它允许在单独的外部进程中启动每个Junit测试方法,我已经在GitHubmaven central中发布了它,可能是插件合适您的问题的解决方案,该插件还允许使用不同的 JVM 启动此类测试

于 2015-05-17T16:24:50.437 回答
0

使用ProcessBuilder API,您可以在启动每个进程之前更改环境变量。这是一个代码片段,您可以如何做到这一点。

 @Test
 void testVariant1(){
      String [] commandArray = 
        {"java", "-cp", "your/class/path", "org.mydomain.myClass", ...};
      Map<String, String> envVarsForThisTest = new HashMap<String, String>();
      envVarsForThisTest.put("newProperty", "value1");
      List<String> staleVars = new List<String>();
      stateVars.add("oldProperty");
      File workingDir = new File("myDir"));
      Process p = runVariant(
                commandArray, envVarsForThisTest, staleVars, workingDir);
      Assert.assert(p.waitFor(), 0);
      checkAssertions(p.getOutputStream(), p.getErrorStream());
 }

 void checkAssertions(OutputStream output, InputStream errorStream){
      // where you'll check the return values against your expectations
 }

 void runVariant(String commandArray[], 
           Map<String, 
           String> newEnvironmentVariables, 
           List<String> environemntVariablesToRemove, 
           File workingDirectory){
      ProcessBuilder pb = new ProcessBuilder(commandArray);
      Map<String, String> env = pb.environment();
      for(Map.Entry<String, String> entry : newEnvironmentVariables){
           env.put(entry.key(), entry.value());
      }
      for(String staleVariable : environemntVariablesToRemove){
           env.remove(staleVariable);
      }
      pb.directory(workingDirectory);
      return pb.start();
 }
于 2012-09-03T11:29:17.210 回答
-2

单元测试通常不应依赖于远程服务器等外部资源。否则,您不是在测试单元,而是在测试它所依赖的资源的可用性和正确性。

那么如何测试这些单元呢?

您通常使用模拟对象执行此操作。您将对外部资源的调用封装在一个对象中,并将该对象传递给您要测试的单元(称为依赖注入)。在您的单元测试中,您没有传递真正的服务器抽象对象。相反,您传递的是实现相同接口或扩展服务器抽象类的模拟对象。模拟对象并不真正查询服务器。相反,它立即返回服务器应返回的值。

这可能需要对您的代码进行一些重构。但它允许您的单元测试在不依赖外部资源的情况下工作。它还使测试变得更快,从而减少了测试套件的整体执行时间。这使您可以更频繁地执行单元测试

于 2012-09-03T10:26:17.520 回答