Mockito: Trying to spy on method is calling the original method
Let me quote the official documentation:
Important gotcha on spying real objects!
Sometimes it's impossible to use when(Object) for stubbing spies. Example:
List list = new LinkedList();
List spy = spy(list);
// Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
when(spy.get(0)).thenReturn("foo");
// You have to use doReturn() for stubbing
doReturn("foo").when(spy).get(0);
In your case it goes something like:
doReturn(resultsIWant).when(myClassSpy).method1();
Original Method Called even after using Mockito.Spy
It got solved. Apparently, I was sending any(JSONObject.class)
while using service1.sendFunc(any(JSONObject.class))
but when I sent new JSONObject()
it worked properly.
Thanks for helping!
Mockito Spy doReturn calls original method
The issue is caused by a type mismatch on the parameter being passed to method2
. That's what this part of the exception message is telling you:
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Misplaced argument matcher detected here:
The following test passes:
@Test
public void test01(){
MyClass spyMyClass = spy(myClass);
doReturn(28).when(spyMyClass).method2(anyInt());
int a = spyMyClass.method1();
assertTrue("We did it!!!",a==28);
}
There are two changes here:
- Use
anyInt()
instead ofany()
- Assert that
a==28
because you are telling the stub to return28
Mockito spy method being called during unit test
stackoverflow recommended this as related and it solved my issue:
Mockito: Trying to spy on method is calling the original method
Basically, using doReturn instead of when.
Mockito.doReturn(true).when(sampleSpy).methodB(Mockito.any(String.class),Mockito.any(String.class));
Also helpful response: Mockito - difference between doReturn() and when()
Spy a class without PowerMock
During mockStatic
definition in Mockito you can specify setting to perform real execution by default Mockito.withSettings().defaultAnswer(Mockito.CALLS_REAL_METHODS)
. In this way, your static mock will work like Spy
.
Let's create simple Utils
class for testing.
public class Utils {
public static String method1() {
return "Original mehtod1() value";
}
public static String method2() {
return "Original mehtod2() value";
}
public static String method3() {
return method2();
}
}
Make mock for method2
and perform real execution of method1
and method3
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
public class SpyStaticTest {
@Test
public void spy_static_test() {
try (MockedStatic<Utils> utilities = Mockito.mockStatic(Utils.class, Mockito.withSettings().defaultAnswer(Mockito.CALLS_REAL_METHODS))) {
utilities.when(Utils::method2).thenReturn("static mock");
Assertions.assertEquals(Utils.method1(), "Original mehtod1() value");
Assertions.assertEquals(Utils.method2(), "static mock");
Assertions.assertEquals(Utils.method3(), "static mock");
}
}
}
Example for your class:
@Test
public void test() {
try (MockedStatic<MessageValidationUtils> utilities = Mockito.mockStatic(MessageValidationUtils.class, Mockito.withSettings().defaultAnswer(Mockito.CALLS_REAL_METHODS))) {
utilities.when(() -> MessageValidationUtils.validateTelegramKeyMap(messageProcessDto.getMessageMessageType(),
messageProcessDto.getMessageKeyValueMap())).thenAnswer((Answer<Boolean>) invocation -> true);
//perform testing of your service which uses MessageValidationUtils
}
}
UPDATE:
Example to use mockStatic
in @BeforeEach
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
public class SpyStaticTest {
MockedStatic<Utils> utilities;
@BeforeEach
public void setUp() {
utilities = Mockito.mockStatic(Utils.class, Mockito.withSettings().defaultAnswer(Mockito.CALLS_REAL_METHODS));
}
@Test
public void spy_static_test1() {
utilities.when(Utils::method2).thenReturn("static mock");
Assertions.assertEquals(Utils.method1(), "Original mehtod1() value");
Assertions.assertEquals(Utils.method2(), "static mock");
Assertions.assertEquals(Utils.method3(), "static mock");
}
@Test
public void spy_static_test2() {
utilities.when(Utils::method1).thenReturn("static mock");
Assertions.assertEquals(Utils.method1(), "static mock");
Assertions.assertEquals(Utils.method2(), "Original mehtod2() value");
Assertions.assertEquals(Utils.method3(), "Original mehtod2() value");
}
@AfterEach
public void afterTest() {
utilities.close();
}
}
UPDATE:
Mockito does not provide method for static Spy
creation, but you can define own utils and implemet spy static definition there.
import org.mockito.MockedStatic;
import org.mockito.Mockito;
public class MockitoUtils {
public static <T> MockedStatic<T> spyStatic(Class<T> classToMock) {
return Mockito.mockStatic(classToMock, Mockito.withSettings().defaultAnswer(Mockito.CALLS_REAL_METHODS));
}
}
In this way your tests will look more clear:
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import static com.test.MockitoUtils.spyStatic;
public class SpyStaticTest {
MockedStatic<Utils> utilsSpy;
@BeforeEach
public void setUp() {
utilsSpy = spyStatic(Utils.class);
}
@Test
public void spy_static_test1() {
utilsSpy.when(Utils::method2).thenReturn("static mock");
Assertions.assertEquals(Utils.method1(), "Original mehtod1() value");
Assertions.assertEquals(Utils.method2(), "static mock");
Assertions.assertEquals(Utils.method3(), "static mock");
}
@Test
public void spy_static_test2() {
utilsSpy.when(Utils::method1).thenReturn("static mock");
Assertions.assertEquals(Utils.method1(), "static mock");
Assertions.assertEquals(Utils.method2(), "Original mehtod2() value");
Assertions.assertEquals(Utils.method3(), "Original mehtod2() value");
}
@AfterEach
public void afterTest() {
utilsSpy.close();
}
}
Related Topics
Bidirectional Multi-Valued Map in Java
Immutable VS Unmodifiable Collection
Difference Between Java.Exe and Javaw.Exe
Java, Simplified Check If Int Array Contains Int
CSV Parsing in Java - Working Example
Rotating Image with Affinetransform
Persistence Unit as Resource_Local or Jta
Java: How to Import a Jar File from Command Line
The Resourceconfig Instance Does Not Contain Any Root Resource Classes
Using Jasperreports with a Relative Path
Maven: Failed to Read Artifact Descriptor
How to Change an Eclipse Default Project into a Java Project
How to Get Absolute Path to File in /Resources Folder of Your Project
In What Order Are Static Blocks and Static Variables in a Class Executed