AEM Mocks fails with "No OSGi SCR metadata found for class ..."

Problem

When you execut your Unit Tests using AEM Mocks, Sling Mocks or OSGi Mocks you may encounter a stack trace like this:

java.lang.RuntimeException: After setup failed (io.wcm.handler.link.testcontext.AppAemContext$1@189cbd7c): No OSGi SCR metadata found for class io.wcm.handler.link.impl.LinkHandlerConfigAdapterFactory
  at org.apache.sling.testing.mock.osgi.context.ContextPlugins.executeAfterSetUpCallback(ContextPlugins.java:218)
  at io.wcm.testing.mock.aem.junit.AemContext$1.before(AemContext.java:184)
  at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:46)
  at org.junit.rules.RunRules.evaluate(RunRules.java:20)
  at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
  at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
  at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
  at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
  at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
  at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
  at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
  at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)
Caused by: org.apache.sling.testing.mock.osgi.NoScrMetadataException: No OSGi SCR metadata found for class io.wcm.handler.link.impl.LinkHandlerConfigAdapterFactory
  at org.apache.sling.testing.mock.osgi.OsgiServiceUtil.injectServices(OsgiServiceUtil.java:383)
  at org.apache.sling.testing.mock.osgi.MockOsgi.injectServices(MockOsgi.java:163)
  at org.apache.sling.testing.mock.osgi.context.OsgiContextImpl.registerInjectActivateService(OsgiContextImpl.java:158)
  at org.apache.sling.testing.mock.osgi.context.OsgiContextImpl.registerInjectActivateService(OsgiContextImpl.java:146)
  at io.wcm.handler.link.testcontext.AppAemContext$1.execute(AppAemContext.java:99)
  at io.wcm.handler.link.testcontext.AppAemContext$1.execute(AppAemContext.java:1)
  at org.apache.sling.testing.mock.osgi.context.ContextPlugins$2.afterSetUp(ContextPlugins.java:122)
  at org.apache.sling.testing.mock.osgi.context.ContextPlugins.executeAfterSetUpCallback(ContextPlugins.java:215)
  ... 18 more


To run the unit tests in the mocked OSGi environment the OSGi metadata files located in the bundle JAR file at /OSGI-INF need to be present in the folder target/classes during unit test execution. If this stack trace occurs they are not present, and thus the mocked OSGi dos not run.

Solution

Maven Bundle Plugin configuration

First, you have to make sure you have properly set up the maven-bundle-plugin to make sure there is an additional execution of the "manifest" goal, and the configuration parameter "exportScr" is set to true.

See Bundle Plugin FAQ for details, here is an example:

<plugin>
  <groupId>org.apache.felix</groupId>
  <artifactId>maven-bundle-plugin</artifactId>
  <extensions>true</extensions>
  <executions>
    <!-- Configure extra execution of 'manifest' in process-classes phase to make sure SCR metadata is generated before unit test runs -->
    <execution>
      <id>scr-metadata</id>
      <goals>
        <goal>manifest</goal>
      </goals>
      <configuration>
        <supportIncrementalBuild>true</supportIncrementalBuild>
      </configuration>
    </execution>
  </executions>
  <configuration>
    <exportScr>true</exportScr>
    <instructions>
      <!-- Enable processing of OSGI DS component annotations -->
      <_dsannotations>*</_dsannotations>
      <!-- Enable processing of OSGI metatype annotations -->
      <_metatypeannotations>*</_metatypeannotations>
    </instructions>
  </configuration>
</plugin>

If you have used the Adobe AEM Project Archetype or the wcm.io Maven Archetype for AEM this is already correctly configured.

Unit tests fail only in Eclipse

If the Unit Tests fail only in Eclipse, execute a "Project → Clean" command to start a fresh rebuild of the project in Eclipse which should generate the required metadata. It should be done automatically by Eclipse, but sometimes this fails.