PowerMockito mock single static method and return object inside another static method
I found the solution in SOF in somebody's post.
In my case, I have used same partial mock of PowerMockito as below.
PowerMockito.stub(PowerMockito.method(OpenPgpUtility.class, "readPublicKey", InputStream.class)).toReturn(mockPGPPublicKey);
which letting me to mock readPublicKey()
but an actual call to encrypt()
How to mock just one static method in a class using Mockito?
By default all methods are mocked. However, using Mockito.CALLS_REAL_METHODS
you can configure the mock to actually trigger the real methods excluding only one.
For example given the class Sample
:
class Sample{
static String method1(String s) {
return s;
}
static String method2(String s) {
return s;
}
}
If we want to mock only method1
:
@Test
public void singleStaticMethodTest(){
try (MockedStatic<Sample> mocked = Mockito.mockStatic(Sample.class,Mockito.CALLS_REAL_METHODS)) {
mocked.when(() -> Sample.method1(anyString())).thenReturn("bar");
assertEquals("bar", Sample.method1("foo")); // mocked
assertEquals("foo", Sample.method2("foo")); // not mocked
}
}
Be aware that the real Sample.method1()
will still be called. From Mockito.CALLS_REAL_METHODS
docs:
This implementation can be helpful when working with legacy code. When
this implementation is used, unstubbed methods will delegate to the
real implementation. This is a way to create a partial mock object
that calls real methods by default.
...
Note 1: Stubbing partial mocks using
when(mock.getSomething()).thenReturn(fakeValue)
syntax will call the
real method. For partial mock it's recommended to usedoReturn
syntax.
So if you don't want to trigger the stubbed static method at all, the solution would be to use the syntax doReturn
(as the doc suggests) but for static methods is still not supported:
@Test
public void singleStaticMethodTest() {
try (MockedStatic<Sample> mocked = Mockito.mockStatic(Sample.class,Mockito.CALLS_REAL_METHODS)) {
doReturn("bar").when(mocked).method1(anyString()); // Compilation error!
//...
}
}
About this there is an open issue, in particular check this comment.
PowerMock, mock a static method, THEN call real methods on all other statics
What are you looking for is called partial mocking.
In PowerMock you can use mockStaticPartial method.
In PowerMockito you can use stubbing, which will stub only the method defined and leave other unchanged:
PowerMockito.stub(PowerMockito.method(StaticUtilClass.class, "someStaticMethod")).toReturn(5);
also don't forget about the
@PrepareForTest(StaticUtilClass.class)
PowerMockito mockStatic gives MissingMethodInvocationException
I solved it following this, all other solutions didn't work for me. It is difficult to search for this solution, since there are too many on SO on the same.
PowerMockito mock single static method and return object inside another static method , PowerMock, mock a static method, THEN call real methods on all other statics
@RunWith(PowerMockRunner.class)
@PrepareForTest({Base64.class})
public class BqClientFactoryTest {
@Test
public void testGetBigQueryClient() throws Exception {
Base64.Decoder mockDecoder = mock(Base64.Decoder.class);
stub(method(Base64.class, "getDecoder")).toReturn(mockDecoder);
Static mock failing on JDK 17
The difference stems from the fact that JDK 17 no longer calls Clock.systemUTC()
in implementation of Instant.now()
Please compare:
JDK 17:
public static Instant now() {
return Clock.currentInstant();
}
JDK 15:
public static Instant now() {
return Clock.systemUTC().instant();
}
If you insist on mocking static methods, you could stub Instant.now()
, not Clock.systemUTC()
- thus you don't rely on the implementation of Instant.now()
As discussed in the comments in under your post, this is not the recommended approach - class Clock
was designed specifically to make time-handling code easier to test, use a Clock
in your code instead of calling Instant.now()
@Test
void mockStaticClock() {
final Instant instantExpected = Instant.parse("2022-03-10T10:15:30Z");
try (final MockedStatic<Instant> instantMock = mockStatic(Instant.class)) {
instantMock.when(Instant::now).thenReturn(instantExpected);
final Instant now = Instant.now();
assertEquals(instantExpected, now);
}
}
How do I mock a static method call from a nother static method in the same class?
Starting from the docs, with some minor tweaks, you can either mock or spy the static method, depending on what you need (spying seems a bit less verbose but has different syntax). You can find below a sample for both, based on PowerMockito 1.7.3 & Mockito 1.10.19.
Given the following simple class with the required 2 static methods:
public class ClassWithStaticMethods {
public static String doSomething() {
throw new UnsupportedOperationException("Nope!");
}
public static String callDoSomething() {
return doSomething();
}
}
You can do something like:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.powermock.api.mockito.PowerMockito.*;
// prep for the magic show
@RunWith(PowerMockRunner.class)
@PrepareForTest(ClassWithStaticMethods.class)
public class ClassWithStaticMethodsTest {
@Test
public void shouldMockStaticMethod() {
// enable static mocking
mockStatic(ClassWithStaticMethods.class);
// mock the desired method
when(ClassWithStaticMethods.doSomething()).thenReturn("Did something!");
// can't use Mockito.CALLS_REAL_METHODS, so work around it
when(ClassWithStaticMethods.callDoSomething()).thenCallRealMethod();
// validate results
assertThat(ClassWithStaticMethods.callDoSomething(), is("Did something!"));
}
@Test
public void shouldSpyStaticMethod() throws Exception {
// enable static spying
spy(ClassWithStaticMethods.class);
// mock the desired method - pay attention to the different syntax
doReturn("Did something!").when(ClassWithStaticMethods.class, "doSomething");
// validate
assertThat(ClassWithStaticMethods.callDoSomething(), is("Did something!"));
}
}
Related Topics
Java.Sql.Sqlexception: - Ora-01000: Maximum Open Cursors Exceeded
Can Enums Be Subclassed to Add New Elements
Centering a Jlabel on a JPAnel
File Upload Along with Other Object in Jersey Restful Web Service
How to Get a List of Dates Between Two Dates in Java
Where Is Array's Length Property Defined
Tomcat 10.0.4 Doesn't Load Servlets (@Webservlet Classes) with 404 Error
When Should a Class Be Comparable And/Or Comparator
Moving Decimal Places Over in a Double
Can Overridden Methods Differ in Return Type
Setting Background Images in Jframe
Multiple Wildcards on a Generic Methods Makes Java Compiler (And Me!) Very Confused
How to Generate Uml Diagrams (Especially Sequence Diagrams) from Java Code
Closing Database Connections in Java