我在一些单元测试中使用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);
这个相同的代码在同一个类中的其他测试中运行良好,它成功捕获了以相同方式创建相同类型的对象。
任何帮助表示赞赏!感谢
答案 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(被测试的类) )。