I'm using maven to build and test my code before installing to an instance of AEM 5.6.1. I've written unit tests that benefit from aem mocks using an implementation by wcm.io and other unit tests that require mocking static methods using powermockito.
Here are my maven dependencies for the aem-context, sling mocks and powermock.
<dependency>
<groupId>io.wcm</groupId>
<artifactId>io.wcm.testing.aem-mock</artifactId>
<version>1.2.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.resourceresolver</artifactId>
<version>1.1.6</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>r05</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.commons.testing</artifactId>
<version>2.0.14</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.commons.mime</artifactId>
<version>2.1.8</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>1.9.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>1.5.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>1.5.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit-addons</groupId>
<artifactId>junit-addons</artifactId>
<version>1.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.testing.resourceresolver-mock</artifactId>
<version>0.0.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.testing.jcr-mock</artifactId>
<version>0.0.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.testing.sling-mock</artifactId>
<version>0.0.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.testing.osgi-mock</artifactId>
<version>0.0.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.testing.sling-mock-jackrabbit</artifactId>
<version>0.0.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.9.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.junit.core</artifactId>
<version>1.0.8</version>
<scope>test</scope>
</dependency>
In my class I'm setting up the rule for the aem context and preparing some static classes for mocking:
@RunWith(PowerMockRunner.class)
@PrepareForTest({MyStatic.class})
public abstract class MyTest {
@Rule
public final AemContext context = new AemContext();
@Mock
protected MyStatic myStatic;
...
When I run mvn test via the command line I received the following exception:
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 1.431 sec <<< FAILURE! - in com...MyTest
testTest(com.linkedin.aem.components.foundation.components.ParbaseTest) Time elapsed: 0.183 sec <<< ERROR!
java.lang.ExceptionInInitializerError: null
at org.apache.sling.testing.mock.osgi.MockServiceRegistration.readOsgiMetadata(MockServiceRegistration.java:93)
at org.apache.sling.testing.mock.osgi.MockServiceRegistration.<init>(MockServiceRegistration.java:55)
at org.apache.sling.testing.mock.osgi.MockBundleContext.registerService(MockBundleContext.java:80)
at org.apache.sling.testing.mock.osgi.MockBundleContext.registerService(MockBundleContext.java:74)
at org.apache.sling.testing.mock.sling.context.SlingContextImpl.registerService(SlingContextImpl.java:309)
at org.apache.sling.testing.mock.sling.context.SlingContextImpl.registerService(SlingContextImpl.java:294)
at org.apache.sling.testing.mock.sling.context.SlingContextImpl.registerDefaultServices(SlingContextImpl.java:118)
at io.wcm.testing.mock.aem.context.AemContextImpl.registerDefaultServices(AemContextImpl.java:53)
at org.apache.sling.testing.mock.sling.context.SlingContextImpl.setUp(SlingContextImpl.java:102)
at io.wcm.testing.mock.aem.context.AemContextImpl.setUp(AemContextImpl.java:75)
at io.wcm.testing.mock.aem.junit.AemContext.access$000(AemContext.java:40)
at io.wcm.testing.mock.aem.junit.AemContext$1.before(AemContext.java:119)
at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:44)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:91)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:282)
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:207)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:146)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:120)
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:118)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:101)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:53)
at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:264)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:124)
at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:200)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:153)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103)
Caused by: java.lang.ClassCastException: org.apache.xerces.jaxp.DocumentBuilderFactoryImpl cannot be cast to javax.xml.parsers.DocumentBuilderFactory
at javax.xml.parsers.DocumentBuilderFactory.newInstance(DocumentBuilderFactory.java:121)
at org.apache.sling.testing.mock.osgi.OsgiMetadataUtil.<clinit>(OsgiMetadataUtil.java:61)
at org.apache.sling.testing.mock.osgi.MockServiceRegistration.readOsgiMetadata(MockServiceRegistration.java:93)
at org.apache.sling.testing.mock.osgi.MockServiceRegistration.<init>(MockServiceRegistration.java:55)
at org.apache.sling.testing.mock.osgi.MockBundleContext.registerService(MockBundleContext.java:80)
at org.apache.sling.testing.mock.osgi.MockBundleContext.registerService(MockBundleContext.java:74)
at org.apache.sling.testing.mock.sling.context.SlingContextImpl.registerService(SlingContextImpl.java:309)
at org.apache.sling.testing.mock.sling.context.SlingContextImpl.registerService(SlingContextImpl.java:294)
at org.apache.sling.testing.mock.sling.context.SlingContextImpl.registerDefaultServices(SlingContextImpl.java:118)
at io.wcm.testing.mock.aem.context.AemContextImpl.registerDefaultServices(AemContextImpl.java:53)
at org.apache.sling.testing.mock.sling.context.SlingContextImpl.setUp(SlingContextImpl.java:102)
at io.wcm.testing.mock.aem.context.AemContextImpl.setUp(AemContextImpl.java:75)
at io.wcm.testing.mock.aem.junit.AemContext.access$000(AemContext.java:40)
at io.wcm.testing.mock.aem.junit.AemContext$1.before(AemContext.java:119)
at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:44)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:91)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:282)
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:207)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:146)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:120)
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:118)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:101)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:53)
at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:264)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:124)
at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:200)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:153)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103)
If I don't prepare any static classes for the test (remove the @PrepareForTest annotation), the test runs just fine. As soon as I add the annotation (even if empty), I get the issue. I'm left with the following questions:
- Is there anything in my setup I can change to get this to work?
- Does the aem context work with static mocking at all? (potentially with another library)
The issue was resolved by tweaking the version numbers of the test dependencies to the following: