ClassNotFound Error when using mockito to mock a class
Question
I am trying to mock a class using Mockito and also using PowerMock. This is the test
@RunWith(PowerMockRunner.class)
@PrepareForTest(value = Util.class)
public final class FSNS_MLFTUnitTests
{
@Test
public final void testChecksum()
{
final Util mockedServiceB = mock(Util.class);
try
{
whenNew(Util.class).withNoArguments().thenReturn(mockedServiceB);
}
catch (final Exception e)
{
System.out.println("Exception thrown: " + e);
}
}
I get the following error when trying to run the test.
java.lang.ExceptionInInitializerError
at sun.reflect.GeneratedSerializationConstructorAccessor6.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Constructor.java:501)
at org.objenesis.instantiator.sun.SunReflectionFactoryInstantiator.newInstance(SunReflectionFactoryInstantiator.java:40)
at org.objenesis.ObjenesisBase.newInstance(ObjenesisBase.java:59)
at org.mockito.internal.creation.jmock.ClassImposterizer.createProxy(ClassImposterizer.java:120)
at org.mockito.internal.creation.jmock.ClassImposterizer.imposterise(ClassImposterizer.java:60)
at org.powermock.api.mockito.internal.mockcreation.MockCreator.createMethodInvocationControl(MockCreator.java:79)
at org.powermock.api.mockito.internal.mockcreation.MockCreator.mock(MockCreator.java:53)
at org.powermock.api.mockito.PowerMockito.mock(PowerMockito.java:80)
at com.cerner.edc.ccm.host.drivers.fsns.mlft.FSNS_MLFTUnitTests.testChecksum(FSNS_MLFTUnitTests.java:23)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:592)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:66)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:322)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:86)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:94)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:309)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:297)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:84)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:222)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:161)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:135)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:133)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:112)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:44)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: com.system.exception.ExceptionAdapter
at com.util.lang.ClassAssistant.lookupClass(ClassAssistant.java:50)
at com.util.lang.ClassAssistant.lookupClass(ClassAssistant.java:66)
at com.logging.edc.EdcAssistant.getResourceBundle(EdcAssistant.java:113)
at com.logging.edc.EdcLogger.<init>(EdcLogger.java:26)
at com..logging.edc.EdcLoggerManager.getLogger(EdcLoggerManager.java:50)
at com.framework.Util.<clinit>(Util.java:65)
... 36 more
This error is being thrown on the mock(Util.class).
These are the following pom dependencies that I am using:
<dependency>
<groupId>org.powermock.modules</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>1.3.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock.api</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>1.3.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.6</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.8.0</version>
</dependency>
Any help is appreicated.
Thanks!!
Solution
Let's analyse the bottom part of the stacktrace :
Caused by: com.cerner.system.exception.ExceptionAdapter
at com.cerner.system.util.lang.ClassAssistant.lookupClass(ClassAssistant.java:50)
I think it's pretty clear here : the line 50 of com.cerner.system.util.lang.ClassAssistant
is causing a com.cerner.system.exception.ExceptionAdapter
.
at com.cerner.system.util.lang.ClassAssistant.lookupClass(ClassAssistant.java:66)
at com.cerner.system.instrument.logging.edc.EdcAssistant.getResourceBundle(EdcAssistant.java:113)
at com.cerner.system.instrument.logging.edc.EdcLogger.<init>(EdcLogger.java:26)
at com.cerner.system.instrument.logging.edc.EdcLoggerManager.getLogger(EdcLoggerManager.java:50)
It seems the actual construction of com.cerner.system.instrument.logging.edc.EdcLoggerManager
is trying to lookup some class in order to get a logger.
at com.cerner.edc.ccm.host.drivers.framework.Util.<clinit>(Util.java:65)
Here you see <clinit>
instead of a method name, it means that's the static part of the class. Which means that the Util
class can't be load properly by the JVM because an ExceptionAdapter
is raised when the EdcLoggerManger
is getting a logger (line 65 of Util class).
Then on subsequent tries to instantiate a Util
class, the JVM will say hey this class is not found, ie your ClassNotFound
.
How to fix it ?
I don't have much more information on your actual code. But you should inspect why this line com.cerner.system.util.lang.ClassAssistant.lookupClass(ClassAssistant.java:66)
is actually throwing a com.cerner.system.exception.ExceptionAdapter
.
Or you could eventually mock the EdcLoggerManager.getLogger(...).
As a reminder if this code is not legacy, I really encourage you to avoid PowerMock as it will not guard you against bad design (poorly testable code, porr evolutivity, poor maintainability). Instead embrace true OOP design with good practice and patterns where appropriate.