我有两个使用JUnit实现的集成测试。两个测试都执行对远程服务器的调用,服务器目标由环境变量配置:
System.setProperty("property", "value1");
棘手的是,对于2次测试,这些属性必须不同。如果我为每个单元测试设置环境变量它不起作用,因为我们使用的中间件在第一次调用时缓存属性值而不再评估它(对于第二次测试)。
我相信解决方案可能是在单独的流程中运行这些单元测试。我看到了类似的讨论here,但是使用JUnit4可能有更优雅的方式吗?这个问题看起来很常见。 或者可能还有其他方法可以使用不同的配置运行单元测试?
提前感谢任何建议。
答案 0 :(得分:3)
在测试之间具有无法重置的状态被认为是不好的做法。虽然无法轻松测试的代码很常见,但解决方案并不简单。
我会考虑重置缓存的值,即使你有使用反射来做。究竟需要重置的内容取决于库的内部表示。
答案 1 :(得分:2)
这取决于你如何运行JUnit。
如果您希望能够从IDE运行它,或者从构建实现自定义Runner
并使用注释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>
答案 2 :(得分:1)
我需要在使用某些遗留代码时隔离junit测试,因此我开发了一个小型maven插件Jute,它允许在分离的外部进程I have published it in GitHub和maven central中启动每个Junit测试方法,可能是插件将是适合您的问题的解决方案,插件也允许使用不同的JVM启动此类测试
答案 3 :(得分: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();
}
答案 4 :(得分:-1)
单元测试通常不应依赖于远程服务器等外部资源。否则,您不会测试该单元,而是测试它所依赖的资源的可用性和正确性。
那么如何测试这些单位呢?
您通常使用模拟对象执行此操作。您将对外部资源的调用封装在对象中,并将此对象传递给您要测试的单元(称为dependency injection)。在单元测试中,您不传递真正的服务器抽象对象。您正在传递一个实现相同接口的模拟对象或扩展服务器抽象类。模拟对象并不真正查询服务器。相反,它会立即返回服务器应返回的值。
这可能需要对您的代码进行一些重构。但它允许您的单元测试在不依赖外部资源的情况下工作。它还使测试更快,更快,从而减少了测试套装的总体执行时间。这使您可以更频繁地执行单元测试