如何使用JMockIt来模拟System.getenv(String)方法?

5

我现在拥有的

我有一个第三方单例实例,我的测试类依赖于它,而该单例在其构造函数中使用了System.getenv(String)。是否可以模拟这个调用?

我尝试过这个

JMockIt示例

    new Expectations()
    {

        System mockedSystem;
        {
            System.getenv( "FISSK_CONFIG_HOME" ); returns( "." );
        }
    };

但是这会导致一个EXCEPTION_ACCESS_VIOLATION异常并使JVM崩溃。

有没有其他方法来为单元测试设置系统环境变量?

5个回答

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版本中发布。


3

PowerMock似乎可以模拟系统类。

另一种选择(如果你不是在单元测试第三方API),是创建一个Facade来包装第三方API,使其拥有一个漂亮、易于模拟的接口,然后让你的测试类使用这个接口而不是真正的API。

哦,JMockIt也支持这个功能: package playtest;

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
您无法改变环境,但可以改变对其的访问:只需将对 System.getenv() 的调用包装在一个方法或帮助类中,然后进行模拟即可。
[编辑] 现在您的问题是如何更改第三方库的代码。解决方案是使用Java反编译器并修复该类。如果您愿意,也可以提交功能请求。将该新类添加到测试套件中。这样,您的IDE将为测试找到该类。
由于测试代码不进入生产环境,因此您可以运行测试,生产代码将使用原始库。

我认为这意味着他不能这样做,因为它在第三方库中。 - Brian Agnew
反编译该类并修复它。 - Aaron Digulla

1
前段时间,我想要测试 System.exit,并通过使用自定义 SecurityManager找到了解决方案。你可以验证调用是否被执行以及调用的参数,但是使用这种方法,你无法模拟调用的返回值。

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"));
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接