Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I mock a static method that returns void with PowerMock?

I have a few static util methods in my project, some of them just pass or throw an exception. There are a lot of examples out there on how to mock a static method that has a return type other than void. But how can I mock a static method that returns void to just "doNothing()"?

The non-void version uses these lines of codes:

@PrepareForTest(StaticResource.class) 

...

PowerMockito.mockStatic(StaticResource.class); 

...

Mockito.when(StaticResource.getResource("string")).thenReturn("string"); 

However if applied to a StaticResources that returns void, the compile will complain that when(T) is not applicable for void...

Any ideas?

A workaround would probably be to just have all static methods return some Boolean for success but I dislike workarounds.

like image 967
Pete Avatar asked Mar 06 '12 14:03

Pete


People also ask

How do you mock method which returns void?

Mockito provides following methods that can be used to mock void methods. doAnswer() : We can use this to perform some operations when a mocked object method is called that is returning void. doThrow() : We can use doThrow() when we want to stub a void method that throws exception.

Can static methods be mocked?

Mocking a No Argument Static Method As previously mentioned, since Mockito 3.4. 0, we can use the Mockito. mockStatic(Class<T> classToMock) method to mock invocations to static method calls. This method returns a MockedStatic object for our type, which is a scoped mock object.

Can we use PowerMock and Mockito together?

Of course you can – and probably will – use Mockito and PowerMock in the same JUnit test at some point of time.


2 Answers

You can stub a static void method like this:

PowerMockito.doNothing().when(StaticResource.class, "getResource", anyString()); 

Although I'm not sure why you would bother, because when you call mockStatic(StaticResource.class) all static methods in StaticResource are by default stubbed

More useful, you can capture the value passed to StaticResource.getResource() like this:

ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class); PowerMockito.doNothing().when(                StaticResource.class, "getResource", captor.capture()); 

Then you can evaluate the String that was passed to StaticResource.getResource like this:

String resourceName = captor.getValue(); 
like image 61
Justin Rowe Avatar answered Oct 15 '22 13:10

Justin Rowe


Since Mockito 3.4.0, an experimental API was introduced to mock static methods.

The following example code has been tested with Mockito 4.3.1 (testImplementation("org.mockito:mockito-inline:4.3.1), and JUnit Jupiter 5.8.2, OpenJDK 11.

import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.mockito.MockedStatic; import org.mockito.Mockito;  import java.util.UUID;  public class StaticMockTest {      @Test     void showCaseStaticMock() {         try (MockedStatic<StaticMockTest> staticMock = Mockito.mockStatic(StaticMockTest.class)) {             staticMock.when(StaticMockTest::getUUIDValue).thenReturn("Mockito");             Assertions.assertEquals("Mockito", StaticMockTest.getUUIDValue());         }          // Regular UUID         UUID.fromString(StaticMockTest.getUUIDValue());     }      public static String getUUIDValue() {         return UUID.randomUUID().toString();     } } 

Previous Answer, probably Mockito 1.x/2.x with Powermock 1.x/2.x

You can do it the same way you do it with Mockito on real instances. For example you can chain stubs, the following line will make the first call do nothing, then second and future call to getResources will throw the exception :

// the stub of the static method doNothing().doThrow(Exception.class).when(StaticResource.class); StaticResource.getResource("string");      // the use of the mocked static code StaticResource.getResource("string"); // do nothing StaticResource.getResource("string"); // throw Exception 

Thanks to a remark of Matt Lachman, note that if the default answer is not changed at mock creation time, the mock will do nothing by default. Hence writing the following code is equivalent to not writing it.

doNothing().doThrow(Exception.class).when(StaticResource.class);     StaticResource.getResource("string"); 

Though that being said, it can be interesting for colleagues that will read the test that you expect nothing for this particular code. Of course this can be adapted depending on how is perceived understandability of the test.


By the way, in my humble opinion you should avoid mocking static code if your crafting new code. At Mockito we think it's usually a hint to bad design, it might lead to poorly maintainable code. Though existing legacy code is yet another story.

Generally speaking if you need to mock private or static method, then this method does too much and should be externalized in an object that will be injected in the tested object.

Hope that helps.

Regards

like image 36
Brice Avatar answered Oct 15 '22 13:10

Brice