【问题标题】:How to JMockIt System.getenv(String)?如何 JMockIt System.getenv(String)?
【发布时间】:2009-10-27 10:17:02
【问题描述】:
我现在拥有的
我有一个第 3 方单例实例,我的测试类依赖于该实例,并且该单例在其构造函数中使用 System.getenv(String)。可以模拟这个调用吗?
我试过了
JMockIt 示例
new Expectations()
{
System mockedSystem;
{
System.getenv( "FISSK_CONFIG_HOME" ); returns( "." );
}
};
但它给了我一个EXCEPTION_ACCESS_VIOLATION 并使 JVM 崩溃。
还有其他方法可以为单元测试设置系统环境变量吗?
【问题讨论】:
标签:
java
unit-testing
jmockit
【解决方案1】:
在这种情况下,您需要使用部分模拟,以便 JMockit 不会重新定义 System 类中的所有内容。以下测试将通过:
@Test
public void mockSystemGetenvMethod()
{
new Expectations()
{
@Mocked("getenv") System mockedSystem;
{
System.getenv("envVar"); returns(".");
}
};
assertEquals(".", System.getenv("envVar"));
}
我将很快实现一项增强功能,以便在模拟 JRE 类时不会出现此类问题。它应该在 0.992 或 0.993 版本中可用。
【解决方案2】:
PowerMock 接缝能够模拟系统类。
您的另一个选择(假设您没有对第 3 方 API 进行单元测试)是为 Facade 创建一个具有良好、易于模拟的接口的第 3 方 API,并让您的测试类使用它而不是真实的东西.
哦,JMockIt 也支持这个:
打包播放测试;
import static org.junit.Assert.*;
import mockit.*;
import mockit.integration.junit4.JMockit;
import org.junit.*;
import org.junit.runner.RunWith;
@RunWith(JMockit.class)
public class JMockItTest {
@Test
public void mockSystemGetEnv() {
Mockit.setUpMocks(MockSystem.class);
assertEquals("Bye", System.getenv("Hello"));
}
@MockClass(realClass = System.class)
public static class MockSystem {
@Mock
public static String getenv(String str) {
return "Bye";
}
}
}
【解决方案3】:
您无法更改环境,但可以更改对它的访问:只需将对 System.getenv() 的调用包装在方法或帮助器类中,然后对其进行模拟。
[编辑] 现在您的问题是如何更改第三方库的代码。这里的解决方案是使用 Java 反编译器并修复类。如果需要,您也可以发送功能请求。将该新类添加到您的测试套件中。这应该会让你的 IDE 找到测试的类。
由于测试代码没有投入生产,您可以运行测试,生产代码将使用原始库。
【解决方案5】:
@Rogério 答案的更新。
在我使用 JMockit 1.25 的情况下,我必须使用 MockUp API:
@Test
public void mockSystemGetenvMethod(){
new MockUp<System>()
{
@Mock
public String getenv(final String string) {
return "";
}
};
assertEquals(".", System.getenv("envVar"));
}