Mockito: Trying to Spy on Method Is Calling the Original Method

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:

  1. Use anyInt() instead of any()
  2. Assert that a==28 because you are telling the stub to return 28

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



Leave a reply



Submit