我有这个类,我试图在其中模拟 UrlWrapper.class 的对象创建
public class WorkerClass {
private final String url;
public WorkerClass(String url) {
this.url = url;
}
void performOperation(Executor executor) throws IOException {
Runnable runnable = new Runnable() {
@Override
public void run() {
UrlWrapper urlWrapper = null;
try {
urlWrapper = new UrlWrapper(url);
HttpURLConnection connection = (HttpURLConnection) urlWrapper.openConnection();
} catch (Exception e) {
e.printStackTrace();
}
}
};
executor.execute(runnable);
}
}
这是我尝试过的测试代码
@RunWith(PowerMockRunner.class)
@PrepareForTest({UrlWrapper.class, WorkerClass.class})
public class TestClass {
@Before
public void init() throws Exception {
UrlWrapper urlWrapper = Mockito.mock(UrlWrapper.class);
PowerMockito.whenNew(UrlWrapper.class)
.withArguments(Mockito.anyString())
.thenReturn(urlWrapper);
}
@Test
public void test() throws IOException {
Executor executor = new Executor() {
@Override
public void execute(Runnable command) {
command.run();
}
};
WorkerClass workerClass = new WorkerClass("");
workerClass.performOperation(executor);
}
}
但它并没有被 mock 。模拟在没有 Runnable 的情况下也能正常工作。
我在这里缺少什么?
最佳答案
您的问题在这里:
@PrepareForTest({UrlWrapper.class, WorkerClass.class
还有:
Runnable runnable = new Runnable() {
事情是:您没有在Worker类中调用new。您正在创建一个 Worker 的匿名内部类(即 Runnable 实例化) - 并且您正在执行 new 调用。
我看到两个选项:
- 当然,那个匿名内部类......实际上有一个类名。因此,也许您可以使用“损坏的”类名,并将其传递给@PrepareForTest
- 避免以这种方式调用new
我相当怀疑你是否选择了第一个工作选项。即使这有效,也可能是一些非常肮脏的解决方法。
真正的答案是:学习如何编写可测试代码,例如通过观看这些 videos 。您的真正问题是对new的调用。一种解决方案:创建一个为您提供 URL 对象的工厂;然后使用依赖注入(inject)来获取可运行对象中的工厂。
无需 PowerMock(ito) 即可模拟该工厂...突然间,您的整个设计得到了改进;同时它变得更容易测试。
关于java - 使用 powerMockito 在 Runnable 中模拟 new(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44669211/