Java 8
Maven 3.9,7
I want to validate that a private method was called once.
In my pom.xml:
<dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>3.12.4</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-inline</artifactId> <version>3.12.4</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-junit4</artifactId> <version>2.0.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito2</artifactId> <version>2.0.2</version> <scope>test</scope> </dependency> Here's my class:
public class MyClass { @Override public void handle(AttendantRequestEvent event) { String eventId = UUID.randomUUID().toString(); myPrivateMethod(eventId, eventId); } private void myPrivateMethod(String eventId, String eventId2) { System.out.println("myPrivateMethod, eventId = " + eventId + ", eventId2 = " + eventId2); } } Here's the unit test:
import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertNotNull; import static org.mockito.Answers.RETURNS_DEEP_STUBS; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.*; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.*; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @RunWith(PowerMockRunner.class) @PrepareForTest(MyClass.class) public class MyClassTest { @Test public void shouldCallMyPrivateMethod() throws Exception { try (MockedStatic<UUID> utilities = Mockito.mockStatic(UUID.class)) { AssistanceRequestsHandler assistanceRequestsHandlerMock = PowerMockito.spy(new AssistanceRequestsHandler()); String fixedUuid = "a1b2c3d4-e5f6-7890-1234-567890abcdef"; UUID uuidMock = mock(UUID.class); utilities.when(UUID::randomUUID).thenReturn(uuidMock); when(uuidMock.toString()).thenReturn(fixedUuid); // Act assistanceRequestsHandlerMock.handle(new InfoEvent(any())); // Assert PowerMockito.verifyPrivate(assistanceRequestsHandlerMock, times(1)) .invoke("myPrivateMethod", fixedUuid, fixedUuid); } } } And it's working just fine. Here's a result:
myPrivateMethod, eventId = a1b2c3d4-e5f6-7890-1234-567890abcdef, eventId2 = a1b2c3d4-e5f6-7890-1234-567890abcdef Nice.
Now, I want to use a logger in my private method, e.g. something like this (in MyClass.java):
private void myPrivateMethod(String eventId, String eventId2) { Logger.info(this, "myPrivateMethod, eventId_1 = {}, eventId_2 {}", eventId, eventId2); } And the test was successfully passed, but it raised the next error:
ScriptEngineManager providers.next(): javax.script.ScriptEngineFactory: Provider jdk.nashorn.api.scripting.NashornScriptEngineFactory not a subtype 2025-04-25 12:12:15,086 main ERROR Could not reconfigure JMX java.lang.LinkageError: loader constraint violation: loader (instance of org/powermock/core/classloader/javassist/JavassistMockClassLoader) previously initiated loading for a different type with name "javax/management/MBeanServer" at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:757) at org.powermock.core.classloader.javassist.JavassistMockClassLoader.loadUnmockedClass(JavassistMockClassLoader.java:90) at org.powermock.core.classloader.MockClassLoader.loadClassByThisClassLoader(MockClassLoader.java:104) at org.powermock.core.classloader.DeferSupportingClassLoader.loadClass1(DeferSupportingClassLoader.java:147) at org.powermock.core.classloader.DeferSupportingClassLoader.loadClass(DeferSupportingClassLoader.java:98) at java.lang.ClassLoader.loadClass(ClassLoader.java:352) at org.apache.logging.log4j.core.jmx.Server.unregisterAllMatching(Server.java:337)
assistanceRequestsHandlerMock.handle(new InfoEvent(any()));is nonsense.any()must only be used when stubbing or verifying methods. It cannot be used as arguments to other methods and will corrupt Mockito's Matcher stack. That and it simply returnsnull, so the call is effectivelynew InfoEvent(null)(plus, as written: confusing Mockito by having unused matchers on its stack). I'm really not sure if stubbing the staticUUID.randomUUID()function is a good idea. And if I remember corectly, you cannot stubtoString(), but I might be mistaken hereverifyPrivate("myPrivateMethod", anyString(), anyString)), it would be equally "good". If you use two argument captors, you could even assert that both arguments are the same/equal.