简体   繁体   中英

Mockito and Powermock cannot mock ClassLoader

I have the following instruction in Java:

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

I need to mock the ClassLoader returned by MyClass.class.getClassLoader() , using Mockito and Powermock.

I tried with this:

@Mock ClassLoader classLoader;

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

But it doesn't work.

Does anybody know how to do it?

As the comments indicate: you are approaching this on the wrong level.

Looking at your code:

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

You see, the MyClass.class.getClassLoader().getResource(fileName) part; that is "built-in" technology.

What I mean is: unless other parts of your code mess around with the ClassLoader, then the above does exactly what it is supposed to do. There is absolutely no need to test that extensively. You only care about: here class, and file name; something give me a Path. That is what matters to you. Thus: abstract that!

In other words: you just go forward and add that additional abstraction, like:

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

A simple implementation could look like

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

or something alike. Please note: you can write a simple unit test that checks this implementation, too.

But the core point is: instead of making the static call within your production code, you use a (mocked) instance of that interface.

No need for PowerMock, no need for static mocking; just nice, plain mockito stuff!

Besides: the above fixes your design problem. You created hard to test production code; and you don't fix that by using the big PowerMock hammer; you fix it improving the bad design.

You are mocking a new Statement, but you have not any new statement in your Code

As for my understanding, you should:

  • Mock static MyClass
  • Mock getClassLoader()
  • create a mock for ClassLoader
  • mock method getResource

Something as follows:

@Mock ClassLoader classLoader;

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

Also you may need to set at the beginning of your test class the following lines:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM