Mockito和Powermock无法模拟ClassLoader

时间:2017-02-01 11:41:30

标签: java unit-testing mockito

我在Java中有以下指令:

 String path = MyClass.class.getClassLoader().getResource(fileName).getPath();

我需要使用Mockito和Powermock模拟ClassLoader返回的MyClass.class.getClassLoader()

我试过这个:

@Mock ClassLoader classLoader;

whenNew(ClassLoader.class).withAnyArguments().thenReturn(classLoader);

但它没有用。

有人知道怎么做吗?

2 个答案:

答案 0 :(得分:2)

正如评论所示:你正在接近这个错误的水平。

查看您的代码:

String path = MyClass.class.getClassLoader().getResource(fileName).getPath();

你看,MyClass.class.getClassLoader().getResource(fileName)部分;那是"内置"技术

我的意思是:除非您的代码的其他部分混乱使用ClassLoader,否则上面的内容完全按照它应该执行的操作。绝对没有必要进行广泛的测试。你只关心:这里的类和文件名;东西给了我一条路。 那个对你来说很重要。因此:抽象那个!

换句话说:你只需要前进并添加那个额外的抽象,例如:

public interface PathProvider {
   public Path getPathFromUrl(Class<?> clazz);
}

一个简单的实现可能看起来像

public class PathProviderImpl implements PathProvider {
   @Override
   Path getPathFromUrl(Class<?> clazz, String fileName) {
     return clazz.getClassLoader().getResource(fileName).getPath();
}

或类似的东西。请注意:您也可以编写一个简单的单元测试来检查此实现。

但核心要点是:不要在生产代码中进行静态调用,而是使用该接口的(模拟)实例。

不需要PowerMock,不需要静态模拟;只是很好,简单的mockito东西!

此外:以上修复您的设计问题。您创建了难以测试的生产代码;并且你不能通过使用大型PowerMock锤来解决这个问题。你修复它改善糟糕的设计。

答案 1 :(得分:0)

您正在嘲笑新的声明,但您的代码中没有任何新的声明

至于我的理解,你应该:

  • 模拟静态MyClass
  • 模拟getClassLoader()
  • 为ClassLoader创建一个模拟
  • 模拟方法getResource

如下:

@Mock ClassLoader classLoader;

    PowerMockito.mockStatic(MyClass.class);
    BDDMockito.given(MyClass.getClassLoader()).willReturn(classLoader);
    PowerMockito.doReturn("desiredResource").when(classLoader).getResource(Mockito.anyString());

此外,您可能需要在测试类的开头设置以下行:

@RunWith(PowerMockRunner.class)
@PowerMockListener(AnnotationEnabler.class)
@PrepareForTest({MyClass.class})
public class yourTestClass....