使用powerMockito在Runnable中模拟new()

时间:2017-06-21 07:15:49

标签: java unit-testing mockito inner-classes powermockito

我有这个类,我正在尝试模拟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);
  }
}

但它没有被嘲笑。没有Runnable,模拟工作正常。

我在这里缺少什么?

1 个答案:

答案 0 :(得分:1)

您的问题在这里

@PrepareForTest({UrlWrapper.class, WorkerClass.class

然后:

Runnable runnable = new Runnable() {

事情是:您工作人员类中调用 new 。您正在创建一个匿名内部类的Worker(即Runnable实例化) - 并且您正在进行 new 调用。

我看到两个选项:

  • 当然,那个匿名的内部类......实际上有一个类名。所以,也许你可以使用“受损”类名,并将其传递给@PrepareForTest
  • 避免以这种方式调用 new

我怀疑你是第一个工作的选择。即使这样可行,也可能是一些非常肮脏的解决方法。

真实答案是:了解如何编写可测试代码,例如通过观看这些videos。您的真正的问题是对 new 的调用。一个解决方案:创建一个工厂,为您提供URL对象;然后使用依赖注入来获取runnable中的工厂。

没有PowerMock(ito)就可以嘲笑那个工厂......突然间,你的整个设计得到了改进;同时,它变得更容易测试。