我是JMockit的新手,但我出于某种原因无法模拟System.getProperties()。感谢以下帖子的帮助:
我可以使用JMockit 1.12成功模拟System.getProperty():
@Test
public void testAddSystemProperty_String() {
final String propertyName = "foo";
final String propertyValue = "bar";
new Expectations(System.class) {{
System.getProperty(propertyName);
returns(propertyValue);
}};
assertEquals(propertyValue, System.getProperty(propertyName));
}
但是用于模拟getProperties()barfs的怪异类似代码:
@Test
public void testAddSystemProperty_String() {
final String propertyName = "foo";
final String propertyValue = "bar";
final Properties properties = new Properties();
properties.setProperty(propertyName, propertyValue);
new Expectations(System.class) {{
System.getProperties();
returns(properties);
}};
assertEquals(1, System.getProperties().size());
}
我得到以下异常,指向"返回"方法:
Missing invocation to mocked type at this point;
please make sure such invocations appear only after
the declaration of a suitable mock field or parameter
另外,我如何同时模拟这两种方法?如果我将它们放在相同的Expectations块中(首先使用getProperty()),那么我没有看到异常,但System.getProperties()返回真实的系统属性,而不是模拟的属性;虽然getProperty(propertyName)返回模拟值。我发现这种行为非常不稳定。
我在这篇文章中看到某些方法无法模拟,但System.getProperties()不在该列表中:
JMockit NullPointerException on Exceptions block?
我也发现,2年前与JMockit合作的很多解决方案现在完全无法编译,所以显然事情发生了很大变化。
答案 0 :(得分:1)
System.getProperties()
确实是在JMockit 1.12中被排除在模拟之外的方法之一。由于找到了新的有问题的JRE方法,这些被排除的方法的确切集合可能会在较新版本中发生变化。
但是,无需模拟System.getProperty(...)
或System.getProperties()
。 System
类提供了setProperty
和setProperties
方法,可以替代使用。
答案 1 :(得分:0)
希望其他人觉得这很有用:
这可以通过Mockito / PowerMock(1.5.3)解决。
请注意,我正在测试一个实用程序,该实用程序将详尽地尝试在给定可能来源列表的情况下查找属性值。源可以是系统属性,环境变量,元信息服务文件,jndi名称,线程本地,磁盘上的文件,ldap,基本上任何可以执行查找的内容。
@RunWith(PowerMockRunner.class)
@PrepareForTest({ClassThatDirectlyCallsSystemInCaseItIsNestedLikeInMyCase.class})
public class ConfigPropertyBuilderTest {
@Test
public void testAddSystemProperty_String_using_PowerMockito() {
PowerMockito.mockStatic(System.class);
PowerMockito.when(System.getProperty(propertyName)).thenReturn(propertyValue);
PowerMockito.when(System.getProperties()).thenReturn(new Properties() {{
setProperty(propertyName, propertyValue);
}});
// Here is realistic case of calling something that eventually calls System
// new configBuilder().addEnvironmentVariable(propertyName)
// .addSystemProperty(propertyName)
// .getValue();
// Here is simplified case:
assertEquals(1, System.getProperties().size());
assertEquals(propertyValue, System.getProperty(propertyName));
}
}
我可以调用System.setProperty(),但是当你开始进入其他来源时,它就变得不那么清楚了。
请注意,我并不特别关心System.getProperty()返回的值;我只想确保在第一次查找失败时调用它。
例如,在上面的代码片段中,环境变量不存在,因此应该调用System.getProperty()。如果环境变量存在(就像在下一个未显示的测试用例中那样),那么我想验证System.getProperty()是否不被调用,因为它应该已经短路。
由于使用真实文件,真正的ldap,真实的API等伪造其他来源的困难,并且因为我想验证某些API是被调用还是未被调用,并且因为我想让测试保持一致,我认为嘲笑是正确的方法(即使我可能试图模拟不推荐的东西,以保持一切看起来一致)。如果您不这么认真,请告诉我。
另外,虽然我不了解维护这些模拟框架(特别是基于cglib的框架)的困难,但我理解存在的困难,我可以理解你遇到的那些问题。我的帽子落到了你们身上。