Apache
Home » Documentation » Development

Sling Mocks

Mock implementation of selected Sling APIs for easier testing.

Maven Dependency

1
2
3
4
<dependency>
  <groupId>org.apache.sling</groupId>
  <artifactId>org.apache.sling.testing.sling-mock</artifactId>
</dependency>

See latest version on the downloads page.

Implemented mock features

The mock implementation supports:

The following features are not supported:

Additional features

Additional features provided:

Usage

Sling Context JUnit Rule

The Sling mock context can be injected into a JUnit test using a custom JUnit rule named SlingContext. This rules takes care of all initialization and cleanup tasks required to make sure all unit tests can run independently (and in parallel, if required).

Example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
public class ExampleTest {

  @Rule
  public final SlingContext context = new SlingContext();

  @Test
  public void testSomething() {
    Resource resource = context.resourceResolver().getResource("/content/sample/en");
    // further testing
  }

}

It is possible to combine such a unit test rule with a @RunWith annotation e.g. for Mockito JUnit Runner.

The SlingContext object provides access to mock implementations of:

Additionally it supports:

Choosing Resource Resolver Mock Type

The Sling mock context supports different resource resolver types. Example:

1
2
3
4
5
6
public class ExampleTest {

  @Rule
  public final SlingContext context = new SlingContext(ResourceResolverType.RESOURCERESOLVER_MOCK);

}

Different resource resolver mock types are supported with pros and cons, see next chapter for details.

Resource Resolver Types

The Sling Mocks resource resolver implementation supports different "types" of adapters for the mocks. Depending on the type an underlying JCR repository is used or not, and the data is stored in-memory or in a real repository.

Resource resolver types currently supported:

RESOURCERESOLVER_MOCK (default)

JCR_MOCK

NONE

JCR_OAK

To use this type you have to declare an additional dependency in your test project:

1
2
3
4
5
<dependency>
  <groupId>org.apache.sling</groupId>
  <artifactId>org.apache.sling.testing.sling-mock-oak</artifactId>
  <scope>test</scope>
</dependency>

See latest version on the downloads page.

JCR_JACKRABBIT

To use this type you have to declare an additional dependency in your test project:

1
2
3
4
5
<dependency>
  <groupId>org.apache.sling</groupId>
  <artifactId>org.apache.sling.testing.sling-mock-jackrabbit</artifactId>
  <scope>test</scope>
</dependency>

See latest version on the downloads page.

Remarks on the JCR_JACKRABBIT type:

Sling Resource Resolver

Example:

1
2
3
4
5
// get a resource resolver
ResourceResolver resolver = MockSling.newResourceResolver();

// get a resource resolver backed by a specific repository type
ResourceResolver resolver = MockSling.newResourceResolver(ResourceResolverType.JCR_MOCK);

If you use the SlingContext JUnit rule you case just use context.resourceResolver().

Adapter Factories

You can register your own or existing adapter factories to support adaptions e.g. for classes extending SlingAdaptable.

Example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// register adapter factory
BundleContext bundleContext = MockOsgi.newBundleContext();
MockSling.setAdapterManagerBundleContext(bundleContext);
bundleContext.registerService(myAdapterFactory);

// test adaption
MyClass object = resource.adaptTo(MyClass.class);

// cleanup after unit test
MockSling.clearAdapterManagerBundleContext();

Make sure you clean up the adapter manager bundle association after running the unit test otherwise it can interfere with the following tests. If you use the SlingContext JUnit rule this is done automatically for you.

If you use the SlingContext JUnit rule you case just use context.registerService().

SlingScriptHelper

Example:

1
2
3
4
5
6
7
8
// get script helper
SlingScriptHelper scriptHelper = MockSling.newSlingScriptHelper();

// get request
SlingHttpServletRequest request = scriptHelper.getRequest();

// get service
MyService object = scriptHelper.getService(MyService.class);

To support getting OSGi services you have to register them via the BundleContext interface of the JCR Mocks before. You can use an alternative factory method for the SlingScriptHelper providing existing instances of request, response and bundle context.

If you use the SlingContext JUnit rule you case just use context.slingScriptHelper().

SlingHttpServletRequest

Example for preparing a sling request with custom request data:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// prepare sling request
ResourceResolver resourceResolver = MockSling.newResourceResolver();
MockSlingHttpServletRequest request = new MockSlingHttpServletRequest(resourceResolver);

// simulate query string
request.setQueryString("param1=aaa&param2=bbb");

// alternative - set query parameters as map
request.setParameterMap(ImmutableMap.<String,Object>builder()
    .put("param1", "aaa")
    .put("param2", "bbb")
    .build());

// set current resource
request.setResource(resourceResolver.getResource("/content/sample"));

// set sling request path info properties
MockRequestPathInfo requestPathInfo = (MockRequestPathInfo)request.getRequestPathInfo();
requestPathInfo.setSelectorString("selector1.selector2");
requestPathInfo.setExtension("html");

// set method
request.setMethod(HttpConstants.METHOD_POST);

// set attributes
request.setAttribute("attr1", "value1");

// set headers
request.addHeader("header1", "value1");

// set cookies
request.addCookie(new Cookie("cookie1", "value1"));

SlingHttpServletResponse

Example for preparing a sling response which can collect the data that was written to it:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
// prepare sling response
MockSlingHttpServletResponse response = new MockSlingHttpServletResponse();

// execute your unit test code that writes to the response...

// validate status code
assertEquals(HttpServletResponse.SC_OK, response.getStatus());

// validate content type and content length
assertEquals("text/plain;charset=UTF-8", response.getContentType());
assertEquals(CharEncoding.UTF_8, response.getCharacterEncoding());
assertEquals(55, response.getContentLength());

// validate headers
assertTrue(response.containsHeader("header1"));
assertEquals("5", response.getHeader("header2"));

// validate response body as string
assertEquals(TEST_CONTENT, response.getOutputAsString());

// validate response body as binary data
assertArrayEquals(TEST_DATA, response.getOutput());

Import resource data from JSON file in classpath

With the ContentLoader it is possible to import structured resource and property data from a JSON file stored in the classpath beneath the unit tests. This data can be used as text fixture for unit tests.

Example JSON data:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
{
  "jcr:primaryType": "app:Page",
  "jcr:content": {
    "jcr:primaryType": "app:PageContent",
    "jcr:title": "English",
    "app:template": "/apps/sample/templates/homepage",
    "sling:resourceType": "sample/components/homepage",
    "jcr:createdBy": "admin",
    "jcr:created": "Thu Aug 07 2014 16:32:59 GMT+0200",
    "par": {
      "jcr:primaryType": "nt:unstructured",
      "sling:resourceType": "foundation/components/parsys",
      "colctrl": {
        "jcr:primaryType": "nt:unstructured",
        "layout": "2;colctrl-lt0",
        "sling:resourceType": "foundation/components/parsys/colctrl"
      }
    }
  }
}

Example code to import the JSON data:

1
2
ContentLoader contentLoader = new ContentLoader(resolver);
contentLoader.json("/sample-data.json", "/content/sample/en");

This codes creates a new resource at /content/sample/en (and - if not existent - the parent resources) and imports the JSON data to this node. It can be accessed using the Sling Resource or JCR API afterwards.

If you use the SlingContext JUnit rule you case just use context.load().

Import binary data from file in classpath

With the ContentLoader it is possible to import a binary file stored in the classpath beneath the unit tests. The data is stored using a nt:file/nt:resource or nt:resource node type.

Example code to import a binary file:

1
2
ContentLoader contentLoader = new ContentLoader(resolver);
contentLoader.binaryFile("/sample-file.gif", "/content/binary/sample-file.gif");

This codes creates a new resource at /content/binary/sample-file.gif (and - if not existent - the parent resources) and imports the binary data to a jcr:content subnode.

If you use the SlingContext JUnit rule you case just use context.load().

Building content

For easily building resources a ContentBuilder provides convenience methods.

Example:

1
2
3
4
5
ContentBuilder contentBuilder = new ContentBuilder(resolver);
contentBuilder.resource("/content/test1", ImmutableMap.<String, Object>builder()
        .put("prop1", "value1")
        .put("prop2", "value2")
        .build());

If you use the SlingContext JUnit rule you case just use context.create().

Rev. 1719223 by sseifert on Thu, 10 Dec 2015 22:08:17 +0000
Apache Sling, Sling, Apache, the Apache feather logo, and the Apache Sling project logo are trademarks of The Apache Software Foundation. All other marks mentioned may be trademarks or registered trademarks of their respective owners.