Tags
Share
It’s difficult to imagine a modern software application that can live without JUnit tests. In a previous article on JUnit testing, JUnit Tests for WCMUsePojo Objects, we included a tip involving a project we were working on. For this article, we use the same project and extend the approach with sling models and a direct connection to a real AEM repository.
In our case, we encountered a problem when we had to test a big back-end service that had a lot of dependencies with other services, data, and web content inside a JCR repository. Creating JUnit tests for AEM components and services requires preparing tons of data, so we implemented a solution that helps save time in preparing all of this data. We were able to use a real repository and data prepared in AEM using all of AEM’s capabilities. This solution significantly sped up writing tests and improved the quality of tests.
Connecting a JUnit test to AEM is a no-brainer requiring just a few simple steps:
- Download a class package https://github.com/apache/sling-org-apache-sling-testing-sling-mock-oak/tree/master/src/main/java/org/apache/sling/testing/mock/sling/oak
- Include the WEB DAV repository factory
org.apache.jackrabbit:jackrabbit-jcr2davdependency in your pom.xml file - Modify the OakMockSlingRepository class from the first step to use the ProxyRepository Connection. Here’s just the changed code:
private SimpleCredentials simpleCredentials;
private ProxyRepository proxyRepository;
@Activate
protected void activate(BundleContext bundleContext) {
executor = Executors.newSingleThreadExecutor();
scheduledExecutor = Executors.newSingleThreadScheduledExecutor();
if (bundleContext.getServiceReference(Executor.class) == null) {
bundleContext.registerService(Executor.class, executor, null);
}
try {
simpleCredentials = new SimpleCredentials("[AEM user]", “[password]”);
proxyRepository = new ProxyRepository(mode.getPath() + "/crx/server");
Session session = proxyRepository.login(simpleCredentials);
repository = session.getRepository();
} catch (Exception e) {
//TODO
}
}
public Session loginAdministrative(String workspaceName) throws RepositoryException {
return proxyRepository.login(simpleCredentials);//you possibly want to use admin creds
}
Now you can declare an AemContext Test Rule in your test cases:
@Rule
public AemContext context = new AemContext(ResourceResolverType.JCR_OAK);
It will use your AEM Repository for tests. Almost anything is possible now, just use a real repository path and adapt to page or sling model:
@Test
public void slingModelTest() throws IOException {
Resource resource = context.resourceResolver().
getResource("/content/blueprint/junit/page");
Page page = resource.adaptTo(Page.class);
ComponentSlingModel model = page.getContentResource().
getChild("main-par/buttoncompone").adaptTo(ComponentSlingModel.class);
//TODO
}
Tips for Additions
Here is a list of nice tips for additions to your tests’ base class that can help you with complex tests:
OSGi configs for the test context
ConfigurationAdmin сonfigurationAdmin = context.getService(ConfigurationAdmin.class);
Dictionary<String, Object> properties = new Hashtable<String, Object>();
properties.put("[key]", "value");
сonfigurationAdmin.getConfiguration("configuration PID").update(properties);
ConfigurationAdmin сonfigurationAdmin = context.getService(ConfigurationAdmin.class);
Dictionary<String, Object> properties = new Hashtable<String, Object>();
properties.put("[key]", "value");
сonfigurationAdmin.getConfiguration("configuration PID").update(properties);
Run modes for the test context
MockSlingSettingService settingService = (MockSlingSettingService)
context.getService(SlingSettingsService.class);
Set<String> runModes = new HashSet<>();
Collections.addAll(runModes, "author", "qa");
settingService.setRunModes(runModes);
Inject and Activate services (any of your real services or external services like GenericListAdapterFactory)
context.registerInjectActivateService(new
com.adobe.acs.commons.genericlists.impl.GenericListAdapterFactory());
context.registerInjectActivateService(new MyCacheServiceImpl());
Register any AEM Mock Service without activation, just to satisfy dependencies
context.registerService(CryptoSupport.class, new MockCryptoSupport());
Supply the context and sling models with sling request related objects
Resource mockRequestRes = context.resourceResolver().getResource("/[path]/anypage");
context.request().setResource(resource);
context.request().setServletPath("[sevlet path]");
Page page = anyResource.adaptTo(Page.class);
anyExampleModel.setRequest(context.request());
anyExampleModel.setCurrentPage(page);
anyExampleModel.setSlingScriptHelper(context.slingScriptHelper());
Author: Peter Zhuravlev






