6

我试图模拟对 final 方法的调用ResourceBundle.getString()。使用 PowerMock 1.4.12 和 EasyMock 3.1,调用不会被模拟;而是调用“真实”方法。

我的测试课:

@RunWith(PowerMockRunner.class)
@PrepareForTest(ResourceBundle.class) 
public class TestSuite {
    @Before
    public void setUp() throws Exception {
        ResourceBundle resourceBundleMock = PowerMock.createNiceMock(ResourceBundle.class);
        expect(resourceBundleMock.getString(BundleConstants.QUEUE)).andReturn("Queue");
        PowerMock.replay(resourceBundleMock);

        beanBeingTested.setMessages(resourceBundleMock);
    }
    ...
}

BeanBeingTested 中的代码:

private ResourceBundle messages;
...
String label = messages.getString(BundleConstants.QUEUE);

错误信息:

java.util.MissingResourceException: Can't find resource for bundle $java.util.ResourceBundle$$EnhancerByCGLIB$$e4a02557, key Queue
at java.util.ResourceBundle.getObject(ResourceBundle.java:384)
at java.util.ResourceBundle.getString(ResourceBundle.java:344)
at com.yoyodyne.BeanBeingTested.setUpMenus(BeanBeingTested.java:87)

当我逐步完成测试用例时,调试器将类型显示beanBeingTested.messages为“EasyMock for class java.util.ResourceBundle”,因此模拟被正确注入。(此外,在设置过程中调用getString()内部调用没有错误)。expect()

使用普通模拟而不是漂亮模拟,我收到以下错误:

java.lang.AssertionError: 
  Unexpected method call handleGetObject("Queue"): 
    getString("Queue"): expected: 1, actual: 0

知道我做错了什么吗?

谢谢。

4

3 回答 3

3

您正在 使用 EasyMock创建一个实例。相反,在使用静态方法时,您必须模拟(使用 PowerMock)。

它应该是这样工作的(不过用 EasyMock 3.0 和 PowerMock 1.5 测试过):

@RunWith(PowerMockRunner.class)
@PrepareForTest(ResourceBundle.class) 
public class TestSuite {
    @Before
    public void setUp() throws Exception {
        // mock the class for one method only
        PowerMock.mockStaticNice(ResourceBundle.class, "getString");

        // define mock-behaviour on the class, when calling the static method
        expect(ResourceBundle.getString(BundleConstants.QUEUE)).andReturn("Queue");

        // start the engine
        PowerMock.replayAll();
    }
}

(我知道这个问题已经存在几个月了,但它可能对其他人有所帮助)

于 2013-01-29T14:04:23.140 回答
1

尝试使用:

@PrepareForTest({ResourceBundle.class, BeanBeingTested.class})

只有在 PrepareForTest 中使用 ResourceBundle,当直接从您的单元测试方法调用时,模拟将起作用,但是当从 BeanBeingTested 调用时,您会得到正在使用的真实方法。

这方面缺乏 Powermock 文档。

于 2013-04-19T01:18:41.740 回答
0

为什么还要嘲笑对资源包的调用?通常,我尽量避免嘲笑 java 的具体细节,例如 ArrayList、Date 等。资源包(和 MessageFormat.format())对我来说或多或少属于同一类别。他们通常在基本的字符串上操作,如果这些东西被破坏或改变它们的行为足以破坏测试,那绝对是我想知道的:)

让他们抓住字符串(大概是在 UI 中设置,可能在 之后。不要费心断言返回的值,因为您不希望对包的编辑破坏您的测试。如果字符串被设置在模拟 UI 组件上,这是 anyObject(String.class) 的好地方,它正确地表达了您(可能)实际上并不关心显示的特定字符串的事实。

当测试由于缺少消息密钥而失败时,我也认为这是一个好处。我想知道的。

于 2012-08-23T17:27:18.547 回答