使用PowerMock在多个测试中模拟System.class不能按预期工作

时间:2017-10-18 16:25:34

标签: java junit powermock powermockito

待测班级:

public class SystemCaller {
  public String callSystem() {
    return System.getenv("test-this");
  }
}

测试1:

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;

@RunWith(PowerMockRunner.class)
@PrepareForTest({SystemCaller.class, System.class})
public class SystemTestOne {

    @Before
    public void start() throws Exception {
        PowerMockito.mockStatic(System.class);
        PowerMockito.when(System.getenv("test-this")).thenReturn("hello-one");
    }

    @After
    public void stop() {}

    @Test
    public void verifySystemTestOne() throws Exception {
        assertThat(new SystemCaller().callSystem(), is("hello-one"));
    }
}

测试2:

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;

@RunWith(PowerMockRunner.class)
@PrepareForTest({SystemCaller.class, System.class})
public class SystemTestTwo {

    @Before
    public void start() throws Exception {
        PowerMockito.mockStatic(System.class);
        PowerMockito.when(System.getenv("test-this")).thenReturn("hello-two");
    }

    @After
    public void stop() {}

    @Test
    public void verifySystemTestTwo() throws Exception {
        assertThat(new SystemCaller().callSystem(), is("hello-two"));
    }
}

如果单独运行,每个测试都会自行运行。但是,当我运行所有测试时,测试失败。而且错误也各不相同。有时,断言需要hello-two,但得到hello-one。在其他时间,callSystem()只返回null

这里有设置问题吗?或者,这是因为我嘲笑static方法(在这种情况下在System类上)导致问题?

我的依赖项:

      "org.apache.commons" % "commons-lang3" % "3.5" ::
      "com.squareup.okhttp3" % "okhttp" % "3.6.0" ::
      "com.google.code.gson" % "gson" % "2.8.0" ::
      "com.novocode" % "junit-interface" % "0.8" % "test->default" ::
      "junit" % "junit" % "4.12" % "test" ::
      "org.hamcrest" % "hamcrest-core" % "1.3" % "test" ::
      "org.hamcrest" % "hamcrest-library" % "1.3.RC2" % "test" ::
      "com.squareup.okhttp3" % "mockwebserver" % "3.8.0" % "test" ::
      "org.powermock" % "powermock-core" % "1.6.6" % "test" ::
      "org.powermock" % "powermock-api-mockito" % "1.6.6" % "test" ::
      "org.powermock" % "powermock-module-junit4" % "1.6.6" % "test" ::

更新1:

好的,来自@kevin-welker的使用EnvironmentVariables的建议实际上有效。但是,我发现一个奇怪的问题,当我从Intellij IDEA运行JUnit测试时(使用 JUnit运行配置),一切正常,但是当我通过sbt运行它们时(通过./sbt test)他们失败并出现同样的错误:(。

我利用https://github.com/sbt/junit-interface来运行这些测试,但似乎无法让它们发挥作用。

更新2:

好的!感谢@kevin-welker@stefan-birkner,我让测试按预期工作!由于我只需要运行一些测试,并且它们非常快,我可以在并行性方面失败!

3 个答案:

答案 0 :(得分:2)

有一个微型库来帮助模拟称为System Rules的系统类。使用就像

一样简单
@Rule
public final ProvideSystemProperty myPropertyHasMyValue
    = new ProvideSystemProperty("MyProperty", "MyValue");

答案 1 :(得分:0)

您无法模拟System和其他系统类。这通常就是为什么你创建像你的SystemCaller类这样的包装器,它只包含不可测试的逻辑,你可以模拟它们在代码中的使用位置。

此处有更多信息:https://github.com/powermock/powermock/wiki/Mock-System

答案 2 :(得分:0)

您可以在测试后尝试PowerMockito.doCallRealMethod().when(System.class);(@After或@AfterClass),它应该重置System.class的模拟。