我有一个第三方单例实例,我的测试类依赖于该单例,并且该单例在其构造函数中使用System.getenv(String)
。是否有可能模仿这个电话?
我试过这个
new Expectations()
{
System mockedSystem;
{
System.getenv( "FISSK_CONFIG_HOME" ); returns( "." );
}
};
但它给了我一个EXCEPTION_ACCESS_VIOLATION
并崩溃了JVM。
是否有其他方法可以为单元测试设置系统环境变量?
答案 0 :(得分:15)
在这种情况下,您需要使用部分模拟,以便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版本中提供。
答案 1 :(得分:3)
PowerMock接缝能够模拟系统类。
您的另一个选择(假设您不是第三方API的单元测试)是创建一个for Facade第三方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";
}
}
}
答案 2 :(得分:2)
您无法更改环境,但可以更改对它的访问权限:只需将调用包装到方法或帮助程序类中的System.getenv()
,然后模拟它。
[编辑]现在您的问题是如何更改第三方库的代码。这里的解决方案是使用Java反编译器来修复类。如果需要,您也可以发送功能请求。将该新类添加到测试套件中。这应该让你的IDE找到测试的类。
由于测试代码没有投入生产,您可以运行测试,生产代码将使用原始库。
答案 3 :(得分:1)
前段时间我想test System.exit,并使用custom SecurityManager找到解决方案。您可以验证正在进行的调用以及调用的参数,但是使用此方法,您无法模拟调用的返回值。
答案 4 :(得分:0)
@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"));
}