【问题标题】:Mock System class to get system properties模拟系统类以获取系统属性
【发布时间】:2013-12-22 15:30:15
【问题描述】:

我通过 Eclipse 中的 JVM 参数在系统变量中设置了一个文件夹路径,我试图在我的类中访问它: System.getProperty("my_files_path")

在为此类编写 junit 测试方法时,我尝试模拟此调用,因为测试类不考虑 JVM 参数。我使用 PowerMockito 模拟静态 System 类,并尝试在调用 System.getProperpty 时返回一些路径。

在类级别有 @RunWith(PowerMockRunner.class)@PrepareForTest(System.class) 注释。但是, System 类没有被嘲笑,因此我总是得到空结果。 任何帮助表示赞赏。

【问题讨论】:

    标签: java mocking environment-variables system powermock


    【解决方案1】:

    System.setter 或 getter 方法应该放在用户定义的方法中,并且可以模拟该方法以在单元测试中返回所需的属性。

    public String getSysEnv(){
    return System.getEnv("thisprp");
    }
    

    【讨论】:

    • 它甚至不需要powermock。简单的 mockito 可以模拟上面的调用并返回所需的字符串。
    【解决方案2】:

    系统类被声明为 final,不能被 PowerMock 等库模拟。这里发布的几个答案是不正确的。如果您使用Apache System Utils,您可以使用getEnvironmentVariable 方法而不是直接调用 System.getenv。 SystemUtils 可以被模拟,因为它没有被声明为 final。

    【讨论】:

      【解决方案3】:

      在您的测试中设置系统属性,并确保在测试后使用库System Rules 的规则RestoreSystemProperties 将其恢复。

      public class PathInformationTest {
        private PathFinder pathFinder = new PathFinder();
      
        @Rule
        public TestRule restoreSystemProperties = new RestoreSystemProperties();
      
        @Test
        public void testValidHTMLFilePath() { 
          System.setProperty("my_files_path", "abc");
          assertEquals("abc",pathFinder.getHtmlFolderPath());
        }
      }
      

      【讨论】:

      • 环境变量(使用System.getenv检索)与系统属性(使用System.getProperty检索)不同。
      【解决方案4】:

      Sailaja 添加 System.class,因为根据静态私有模拟的 power mock 指南,您应该添加类以准备测试。

       @PrepareForTest({PathInformation.class,System.class})
      

      希望这有帮助。如果它不起作用,请告诉我

      【讨论】:

        【解决方案5】:

        谢谢萨蒂什。除了稍作修改外,此方法有效。我写了 PrepareForTest(PathFinder.class),为测试用例而不是 System.class 准备我正在测试的类

        另外,由于模拟只工作一次,我在模拟后立即调用了我的方法。 我的代码仅供参考:

        @RunWith(PowerMockRunner.class)
        @PrepareForTest(PathInformation.class)
        public class PathInformationTest {
        
            private PathFinder pathFinder = new PathFinder();
        
        @Test
            public void testValidHTMLFilePath() { 
                PowerMockito.mockStatic(System.class);
                PowerMockito.when(System.getProperty("my_files_path")).thenReturn("abc");
                assertEquals("abc",pathFinder.getHtmlFolderPath());
            }
        }
        

        【讨论】:

          【解决方案6】:
          @RunWith(PowerMockRunner.class)
          @PrepareForTest(System.class)
          public class MySuperClassTest {   
          @Test
          public void test(){ 
              PowerMockito.mockStatic(System.class);
              PowerMockito.when(System.getProperty("java.home")).thenReturn("abc");
              System.out.println(System.getProperty("java.home"));
          }
          } 
          

          【讨论】:

          • 请您分享此代码所需的依赖项。
          【解决方案7】:

          PowerMock 无法以通常的方式模拟某些类。见这里:

          但是,这可能仍然不起作用。按照“好设计”偏好的顺序,您可以回退到这些:

          1. 重构您的代码! 使用系统属性传递文件路径可能不是最好的方法。为什么不使用加载到 Properties 对象中的属性文件?为什么不对需要知道这条路径的组件使用 getter/setter 呢?有很多更好的方法可以做到这一点。

            我认为这样做的唯一原因是您试图将测试工具包装在您“无法”修改的代码周围。

          2. 使用@Before@After 方法将系统属性设置为测试的某个已知值。你甚至可以让它成为@Test 方法本身的一部分。这比尝试通过 PowerMock 模拟要容易得多。只需拨打System.setProperty("my_files_path","fake_path");

          【讨论】:

            猜你喜欢
            • 2015-08-17
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-09-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-06-14
            相关资源
            最近更新 更多