Guys Question: How to mock a static final class which has defined some other static final class?
Problem Description: When I want to write some unit test case for a final class ApplianceRelationshipUtils.java, and in this final class ApplianceRelationshipUtils.java, always invork another static class ApplianceUtilities.java. So I need to use powermock to mock the static class ApplianceUtilities.java like this:
// mock the class for one method only
PowerMock.mockStaticPartialNice(ApplianceUtilities.class,"getApplianceVersion");
But in the ApplianceUtilities.java defined many static final classs like these:
private static final IMesUtils m_mesUtils = new MesUtils();
private static final IEndpointUtilities m_endpointUtils = new DefaultEndpointUtilities(m_mesUtils);
private static final ICasUtilities m_casUtils = new DefaultCasUtilities(m_endpointUtils);
private static final IHAApplianceUtilities m_haUtils = new HAApplianceUtils(m_endpointUtils, m_casUtils);
So when I run the testcase there will throw out some exception as below:
java.lang.NoSuchMethodError: com.ibm.usmi.services.updates.util.RestartUtilities.<init>(Lcom/ibm/usmi/services/updates/util/IRcsUtilities;Lcom/ibm/usmi/services/updates/util/MesUtils;Lcom/ibm/usmi/services/updates/util/IUpdateUtils;)V
at com.ibm.vmi.updates.appliance.util.HAApplianceUtils.<init>(HAApplianceUtils.java:222)
at com.ibm.vmi.updates.appliance.util.ApplianceUtilities.<clinit>(ApplianceUtilities.java:89)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at net.sf.cglib.proxy.Enhancer.setCallbacksHelper(Enhancer.java:616)
at net.sf.cglib.proxy.Enhancer.setThreadCallbacks(Enhancer.java:609)
at net.sf.cglib.proxy.Enhancer.registerCallbacks(Enhancer.java:578)
at org.easymock.internal.ClassProxyFactory.createProxy(ClassProxyFactory.java:194)
at org.easymock.internal.MocksControl.createMock(MocksControl.java:60)
at org.easymock.internal.MocksControl.createMock(MocksControl.java:98)
at org.powermock.api.easymock.PowerMock.doCreateMock(PowerMock.java:2214)
at org.powermock.api.easymock.PowerMock.doMock(PowerMock.java:2163)
at org.powermock.api.easymock.PowerMock.createMock(PowerMock.java:76)
at org.powermock.api.easymock.PowerMock.createPartialMock(PowerMock.java:762)
at com.ibm.vmi.updates.appliance.relationship.ApplianceRelationshipUtilsTest.test_validateApplianceReqs(ApplianceRelationshipUtilsTest.java:77)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:66)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:312)
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:296)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:112)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:73)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:284)
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:209)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:148)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:122)
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:120)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:102)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:42)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
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)
I can confirm those errors are coming from the versions mismatch between Mockito and PowerMock. We should define the dependency versions only in the parent pom.xml
file and reference them in the child module pom.xml
files.
I provide an example here. The child pom.xml
file provided,
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito.version}</version>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
In the parent pom.xml
file provided.
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
...........................................................
<properties>
<powermock.version>1.7.4</powermock.version>
<powermock-api.version>2.0.2</powermock-api.version>
<mockito.version>2.8.9</mockito.version>
</properties>
.............................
</project>