1 aem & tdd it’s so boring… august 6, 2015. 2 testing aem as jcr-based applications jcr...
TRANSCRIPT
1
AEM & TDD
It’s so boring…
AUGUST 6, 2015
2
Testing AEM as JCR-based Applications
JCR testing tools1
Sling API level2
OSGi API level3
AEM application level
4
OSGi
JCR
3
JCR: Dependency
javax.jcr:jcrorg.apache.jackrabbit:jackrabbit-core scope: testorg.apache.jackrabbit:jackrabbit-jcr-commons scope:test
4
JCR: Example
@BeforeClassRepositoryConfig config = RepositoryConfig.create(configStream, TEMP_FOLDER.newFolder().getAbsolutePath());
TransientRepository REPOSITORY = new TransientRepository(config);Credentials credentials = new SimpleCredentials("admin", "admin".toCharArray());REAL_SESSION = REPOSITORY.login(credentials, "default");
@ClassRulepublic static TemporaryFolder TEMP_FOLDER = new TemporaryFolder();
5
Apache Sling artifacts
Sling testing tools
1
JCR Mocks
2
Resource Resolver Mocks
3
Sling Mocks4
OSGi Mocks5
6
Sling Testing Utilities
org.apache.sling : org.apache.sling.commons.testing
public class YourTest extends RepositoryTestBase {
RepositoryUtil.registerNodeType(getSession(), getClass().getClassLoader().getResourceAsStream("cq.cnd"));
Node node = JcrUtil.createPath(“/etc/tags”, SLING_FOLDER, getSession());
}
7
JCR Mocks
org.apache.sling : org.apache.sling.testing.jcr-mock
Supports:1. Reading and writing all data (primitive values, arrays, binary data) via the JCR API;2. Creating any number of nodes and properties (stored in-memory in a hash map);3. Register namespaces;4. Queries are supported by setting expected results for a given query;
Not supported:1. Node types are supported in the API, but their definitions and constraints are not applied;2. Versioning not supported;3. Transactions not supported;4. Observation events can be registered but are ignored;5. Access control always grants access;6. Exporting/Importing data via document and system views not supported;7. Workspace management methods not supported;
8
JCR Mocks Example
org.apache.sling : org.apache.sling.testing.jcr-mock
// get sessionSession session = MockJcr.newSession();
// get repositoryRepository repository = MockJcr.newRepository();// prepare mocked search resultList<Node> resultNodes = ImmutableList.of(node1, node2, node3);// return this result for all queriesMockJcr.setQueryResult(session, resultNodes);// return this result for a specific queryMockJcr.setQueryResult(session, "your query statement", Query.JCR_SQL2, resultNodes);
9
Resource Resolver Mocks
org.apache.sling : org.apache.sling.testing.resourceresolver-mock
Supports:1. All read and write operations of the Sling Resource API2. Mimics transactions using via commit()/revert() methods3. OSGi events for adding/changing/removing resources4. The implementation tries to be as close as possible to the behavior of the JCR resource implementation e.g. concerning date and binary handling
Not supported:1. Authentication not supported ("login" always possible with null authentication info)2. Querying with queryResources/findResources not supported (always returns empty result set)3.Sling Mapping is not supported5. Resolving resource super types
10
Sling Mocks
org.apache.sling : org.apache.sling.testing.sling-mock
Supports:
1. Reading and writing resource data using the Sling Resource API;2. Backed by a mocked or real Jackrabbit JCR implementation;3. Resource-JCR mapping or non-JCR mock implementation;4. Registering adapter factories and resolving adaptions;5. SlingScriptHelper mock implementation;6. SlingHttpServletRequest and SlingHttpServletRequest;7. MockModelAdapterFactory and MimeTypeService;
Not supported:1. It is not possible (nor intended) to really execute sling components/scripts and render their results,
because the goal is to test supporting classes in Sling context, not the sling components/scripts themselves;
11
Sling Mocks: Example
org.apache.sling : org.apache.sling.testing.sling-mock
@Rulepublic final SlingContext context = new SlingContext();
@Testpublic void testSomething() { Resource resource = context.resourceResolver().getResource("/content/sample/en"); // further testing}
RESOURCERESOLVER_MOCK1
JCR_MOCK2
NONE3
JCR_JACKRABBIT4
JCR_OAK5new SlingContext( )
12
Sling Mocks: Example
org.apache.sling : org.apache.sling.testing.sling-mock
// get a resource resolverResourceResolver resolver = MockSling.newResourceResolver();
// get a resource resolver factoryMockSling.newResourceResolverFactory(ResourceResolverType.RESOURCERESOLVER_MOCK);
// get a resource resolver backed by a specific repository typeResourceResolver resolver = MockSling.newResourceResolver(ResourceResolverType.JCR_MOCK);
13
Sling Mocks: Adapter Factories
org.apache.sling : org.apache.sling.testing.sling-mock
// register adapter factoryBundleContext bundleContext = MockOsgi.newBundleContext();MockSling.setAdapterManagerBundleContext(bundleContext);bundleContext.registerService(myAdapterFactory);
// test adaptionMyClass object = resource.adaptTo(MyClass.class);
// cleanup after unit testMockSling.clearAdapterManagerBundleContext();
14
Sling Mocks: Sling Helper, Response, request
org.apache.sling : org.apache.sling.testing.sling-mock
SlingScriptHelper scriptHelper = MockSling.newSlingScriptHelper(); SlingHttpServletRequest request = scriptHelper.getRequest();
// get serviceMyService object = scriptHelper.getService(MyService.class);
MockSlingHttpServletRequest request = new MockSlingHttpServletRequest(resourceResolver);request.setQueryString("param1=aaa¶m2=bbb");request.setResource(resourceResolver.getResource("/content/sample"));
MockSlingHttpServletResponse response = new MockSlingHttpServletResponse();
15
Sling Mocks: Create or Import test data
org.apache.sling : org.apache.sling.testing.sling-mock
ContentLoader contentLoader = new ContentLoader(resolver);contentLoader.json("/sample-data.json", "/content/sample/en");
// Import binary data from file in classpathContentLoader contentLoader = new ContentLoader(resolver);contentLoader.binaryFile("/sample-file.gif", "/content/binary/sample-file.gif");
ContentBuilder contentBuilder = new ContentBuilder(resolver);contentBuilder.resource("/content/test1", ImmutableMap.<String, Object>builder() .put("prop1", "value1").put("prop2", "value2").build());
16
Sling Mocks: OSGi
org.apache.sling : org.apache.sling.testing.osgi-mock
Supports:
1. Bundle, BundleContext and ComponentContext objects and navigate between them;2. Register services;3. Reading metadata from /OSGI-INF/<pid>.xml and from /OSGI-INF/serviceComponents.xml;4. Apply service configuration provided in unit test and from SCR metadata;5. Inject dependencies - static and dynamic;6. Call lifecycle methods for activating, deactivating or modifying;7. Service and bundle listener implementation;8. Mock implementation of LogService which logs to SLF4J in JUnit context;9. Mock implementation of EventAdmin which supports EventHandler services;
17
Sling Mocks: OSGi Example
org.apache.sling : org.apache.sling.testing.osgi-mock
public class OSGiExampleTest { @Rule private final OsgiContext context = new OsgiContext(); @Test public void testSomething() { // register and activate service MyService service1 = context.registerInjectActivateService(new MyService(), ImmutableMap.<String, Object>of("prop1", "value1"));
// get service instance OtherService service2 = context.getService(OtherService.class); }}
18
Sling Mocks: OSGi Example
org.apache.sling : org.apache.sling.testing.osgi-mock
BundleContext bundleContext = MockOsgi.newBundleContext();
BundleContext bundleContext = MockOsgi.newComponentContext(properties, ImmutableMap.<String, Object>of("prop1", "value1"));
// register servicebundleContext.registerService(MyClass.class, myService, properties);// get service instanceServiceReference ref = bundleContext.getServiceReference(MyClass.class.getName());MyClass service = bundleContext.getService(ref)
19
Sling Mocks: OSGi Example
org.apache.sling : org.apache.sling.testing.osgi-mock
// get mock bundle contextBundleContext bundleContext = MockOsgi.newBundleContext();// create service instance manuallyMyService testedService = new MyService();// inject dependenciesMockOsgi.injectServices(testedService, bundleContext);// activate serviceMockOsgi.activate(testedService, props);
// test service...
// deactivate serviceMockOsgi.deactivate(testedService);
20
WCM.IO
wcm.io : io.wcm.testing.aem-mock
21
WCM.IO
wcm.io : io.wcm.testing.aem-mock
Supports:
1. Mocked OSGi, JCR and Sling environment provided by the Apache Sling project;2. Implementation of AEM API level (PageManager, Page, Template, ComponentManager,
Component, TagManager, Tag, Designer, Asset and Rendition);3. JUnit rule AemContext;4. Full support for Sling Models;5. Setting run modes;6. Layer adapter factory;
Not supported:1. Other parts of the AEM API;
22
WCM.IO: Example
wcm.io : io.wcm.testing.aem-mock
public class ExampleTest {
@Rule public final AemContext context = new AemContext();
@Test public void testSomething() { Resource resource = context.resourceResolver().getResource("/content/sample/en"); Page page = resource.adaptTo(Page.class); // further testing }}
23
WCM.IO: Example
wcm.io : io.wcm.testing.aem-mock
public class ExampleTest {@Rulepublic final AemContext context = new AemContext();
@Testpublic void testSomething() {
context.pageManager().create("/content/sample/en", "test1", "/apps/sample/templates/homepage", "title1"); //… Page page = context.pageManager().getPage("/content/sample/en");
Template template = page.getTemplate(); Iterator<Page> childPages = page.listChildren();
// further testing context.pageManager().delete(page, false);
}}
24
WCM.IO: Example
wcm.io : io.wcm.testing.aem-mock
public final AemContext context = new AemContext(new SetUpCallback());
private static final class SetUpCallback implements AemContextCallback { @Override public void execute(final AemContext context) throws PersistenceException, IOException { // application-specific services for unit tests context.registerService(AdapterFactory.class, new AppAdapterFactory()); context.registerService(new AemObjectInjector()); // import sample content context.contentLoader().json("/sample-content.json", "/content/sample/en"); // set default current page context.currentPage("/content/sample/en"); }
25
Q&A?