Powermockito期望在线程中预期的对象创建不起作用

时间:2014-07-25 16:11:34

标签: java junit mockito powermock

我在一些单元测试中使用PowerMockito,并遇到了问题。我试图测试一个创建一系列线程并运行它们的方法。在每个线程内部,创建一个我需要的对象,然后返回我自己的模拟对象(它使http请求等)。我在使用PowerMockito.whenNew(...)之前已经完成了这项工作,并且它工作正常,但这似乎无法正常工作 - PowerMockito在线程中不起作用吗?我还没有找到任何其他类似的问题或有关情况的文件。

一些示例代码可供您查看:

for(Object object : objectList) {
    Thread t = new Thread(new Runnable() {
        public void run() {
            SomeObject objectImTryingToStub = new SomeObject();
        }
    });
}

我用来尝试捕获对象创建的代码:

SomeObject mockSomeObject = mock(SomeObject.class);
PowerMockito.whenNew(SomeObject.class).withNoArguments().thenReturn(mockSomeObject);

这个相同的代码在同一个类中的其他测试中运行良好,它成功捕获了以相同方式创建相同类型的对象。

任何帮助表示赞赏!感谢

5 个答案:

答案 0 :(得分:4)

这里的派对迟到了,但我认为仍然没有找到合适的解决方案。如您所知,您必须PrepareForTest执行您尝试模拟的对象创建的类。不那么明显的是在这里实际进行创作的类。该类是内部匿名Runnable类。此类的名称在编译时生成,在单元测试中不易确定。假设该片段的片段是com.example.SomeClass,那么您需要的语句可能是:

@PrepareForTest(com.example.SomeClass$4.class)

但更简单的方法是使用允许通配符的其他形式的注释:

@PrepareForTest("com.example.*")

尽量让通配符匹配器保持尽可能紧,这样PowerMock就不必为阳光下的每个班级做准备来进行测试。

答案 1 :(得分:3)

我为我的项目遇到了同样的问题,在进行了一些挖掘之后,实际上并没有导致问题本身的线程,而是在从Runnable派生的匿名类中创建了对象。

在PowerMock的doc中,查看第二个要点,您需要放置正在创建的类,而不是在PrepareForTest中实例化的类。

因此,您需要使用PrepareForTest注释您的测试,以准备在运行时创建的匿名类。通常,它将是Runnable $ n,其中n是在运行时为您计算的某个数字。那么你如何获得静态不知道的课程呢?幸运的是,PrepareForTest还在其fullQualifiedNames中接受字符串,因此您需要将PrepareForTest更改为以下内容:

@PrepareForTest( fullyQualifiedNames = {"com.whatever_package_that_SomeObject_is_in.*"}, value = {SomeStaticlyKnowClass.class} )

答案 2 :(得分:1)

对于遇到类似问题的任何人,我进一步研究了它,看起来这个功能并不能完全适用于线程。我试图让它在创建时抛出一个FNF异常 - 在线程中它没有做任何事情,而如果我将对象创建放在线程段之前,它按预期工作。我不确定为什么会这样,但至少我现在有一个确定的答案。如果有人知道解决方法,请告诉我。

答案 3 :(得分:1)

最近,我遇到了同样的问题并找到了解决方案。 真正发生的事情是Runnable的内部声明正在踢你所有的模拟! '因为Runnable类是由引导程序类加载器加载的,所以PowerMock无法模拟其中的任何操作。 解决方案(对我来说)是在Runnable内部类之外声明实例化。

答案 4 :(得分:0)

由于你没有显示很多代码,我不得不猜测你错过了正在进行“新”调用的类的“@PrepareForTest”条目,可能是你的CUT(被测试的类) )。