如何JMockIt System.getenv(String)?

发布于 2024-08-09 11:24:28 字数 407 浏览 8 评论 0原文

我现在

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

我尝试了这个

JMockIt 示例

    new Expectations()
    {

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

,但它给了我一个 EXCEPTION_ACCESS_VIOLATION 并使 JVM 崩溃。

还有另一种方法可以为单元测试设置系统环境变量吗?

What I have right now

I have a 3rd party singleton instance that my class under test relies on and that singleton is using System.getenv(String) in its constructor. Is it possible to mock this call?

I tried this

JMockIt Example

    new Expectations()
    {

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

But it gives me an EXCEPTION_ACCESS_VIOLATION and crashes the JVM.

Is there another way to set a system environment variable for a unit test?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

梦忆晨望 2024-08-16 11:24:28

在这种情况下,您需要使用部分模拟,以便 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 中可用。

In this case you need to use partial mocking so that JMockit doesn't redefine everything in the System class. The following test will pass:

   @Test
   public void mockSystemGetenvMethod()
   {
      new Expectations()
      {
         @Mocked("getenv") System mockedSystem;

         {
            System.getenv("envVar"); returns(".");
         }
      };

      assertEquals(".", System.getenv("envVar"));
   }

I will soon implement an enhancement so that issues like this don't occur when mocking JRE classes. It should be available in release 0.992 or 0.993.

谁的新欢旧爱 2024-08-16 11:24:28

PowerMock 能够模拟系统类。

您的另一个选择(假设您没有对第 3 方 API 进行单元测试)是创建 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";
  }
 }

}

PowerMock seams to be able to mock system classes.

Your other option (assuming you are not unit testing the 3rd party API) is to create a for Facade the 3rd party API that has a nice, easy mockable interface and have your test classes use this rather than the real thing.

Oh, JMockIt supports this too:
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";
  }
 }

}
π浅易 2024-08-16 11:24:28

您无法更改环境,但可以更改对其的访问:只需将对 System.getenv() 的调用包装在方法或辅助类中,然后对其进行模拟。

[编辑] 现在你的问题是如何更改第三方库的代码。这里的解决方案是使用 Java 反编译器并修复该类。如果需要,您也可以发送功能请求。将这个新类添加到您的测试套件中。这应该会让您的 IDE 找到用于测试的类。

由于测试代码不会投入生产,因此您可以运行测试,并且生产代码将使用原始库。

You can't change the environment but you can change the access to it: Simply wrap the call to System.getenv() in a method or a helper class and then mock that.

[EDIT] Now your problem is how to change the code of your third party library. The solution here is to use a Java decompiler and to fix the class. If you want, you can send in a feature request in, too. Add that new class to your test suite. That should make your IDE find the class for the tests.

Since test code doesn't go into production, you can run your tests and the production code will use the original library.

南汐寒笙箫 2024-08-16 11:24:28

不久前,我想测试 System.exit,并发现了一个使用 自定义 SecurityManager。您可以验证正在进行的调用以及调用的参数,但使用此方法,您无法模拟调用的返回值。

A while back I wanted to test System.exit, and found a solution by using a custom SecurityManager. You can verify the call is being made, and the argument of the call, but using this method, you can't mock the return value of the call.

魂ガ小子 2024-08-16 11:24:28

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

An update on @Rogério answer.

In my case with JMockit 1.25 I had to do it using the MockUp API:

@Test
public void mockSystemGetenvMethod(){
    new MockUp<System>()
    {
        @Mock
        public String getenv(final String string) {
            return "";
        }
    };

    assertEquals(".", System.getenv("envVar"));
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文