如何使用Mockito模拟System.getProperty函数

8

我在test/resources/mockito-extensions中的org.mockito.plugins.MockMaker文件中添加了mock-maker-inline文本。

在我的测试用例中,我正在使用:

System system = mock(System.class);
when(system.getProperty("flag")).thenReturn("true");`

但我遇到了以下异常:
org.mockito.exceptions.misusing.MissingMethodInvocationException: 
when() requires an argument which has to be 'a method call on a mock'.
For example:
    when(mock.getArticles()).thenReturn(articles);

Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
   Those methods *cannot* be stubbed/verified.
   Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.

感谢您的建议。

2
为什么需要进行模拟?在测试的设置中,System.setProperty("flag", "true"); 应该可以正常工作。 - Andrew S
3个回答

15

您还可以使用真实的方法,在每个测试之前和之后准备和删除配置:

@Before
public void setUp() {
    System.setProperty("flag", "true");
}

@After
public void tearDown() {
    System.clearProperty("flag");
}

6
< p > System.getProperty() 方法是静态的,如果要进行模拟,您需要使用PowerMock

这里有一个例子:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import static org.junit.Assert.assertEquals;

@RunWith(PowerMockRunner.class)
@PrepareForTest(System.class)
public class ATest {

    @Test
    public void canMockSystemProperties() {
        PowerMockito.mockStatic(System.class);
        PowerMockito.when(System.getProperty("flag")).thenReturn("true");

        assertEquals("true", System.getProperty("flag"));
    }
}

这使用:

  • junit:junit:4.12
  • org.mockito:mocktio-core:2.7.19
  • org.powermock:powermock-api-mockito2:1.7.0
  • org.powermock:powermock-module-junit4:1.7.0
注意:避免使用模拟隐藏所有System访问背后的门面,这是很明智的建议@davidxxx's suggestion。另一种避免需要模拟System的方法是在运行测试时将所需值实际设置为系统属性,System Rules提供了在Junit测试上下文中设置和拆除系统属性期望的简洁方式。

1
System Rules是JUnit的一个附加组件,但它是非常好的一个。可以将它作为一种替代方案来提及。 - davidxxx
不使用 PowerMockito,这是否可能?因为在我的组织中,它不是推荐的 jar 包。 - Pallav Khare

2
Mockito(1作为2)没有提供一种方法来模拟静态方法。 因此,添加mockito-inline将无法模拟System.getProperty()方法。
通常,模拟静态方法往往是一个不好的想法,因为它鼓励了不良设计。 在你的情况下,这并不是这样,因为你需要模拟一个JDK类,当然不能更改。
所以你有两种方式:
1.使用Powermock或任何允许模拟静态方法的工具 2.将System静态方法调用包装在一个提供实例方法的类中,例如SystemService。
最后一种方法真的不难实现,并且除了提供在需要时注入此类的实例之外,还提供了比在两个语句之间隐藏的system.getProperty("flag")语句更清晰的代码。

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