blob: ef81afc4e9114f22d7f5daa8570f9095d93a8b60 [file] [log] [blame]
<!DOCTYPE html><html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<title>Apache Sling :: Sling Mocks</title>
<link rel="icon" href="/favicon.ico"/>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.5/css/bulma.min.css"/>
<link rel="stylesheet" href="/res/css/site.css"/>
<script src='https://www.apachecon.com/event-images/snippet.js'></script><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css"/>
<script src='https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js'></script><script>
hljs.initHighlightingOnLoad();
</script>
<!-- Matomo Web Analytics -->
<script>
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
/* We explicitly disable cookie tracking to avoid privacy issues */
_paq.push(['disableCookies']);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="https://matomo.privacy.apache.org/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '6']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Matomo Code -->
<link href='/pagefind/pagefind-ui.css' rel='stylesheet'><script src='/pagefind/pagefind-ui.js' type='text/javascript'></script>
<script>
window.addEventListener('DOMContentLoaded', (event) => {
new PagefindUI({ element: "#searchbox" });
});
</script>
</head> <body>
<div class="section">
<div class="level is-marginless">
<div class="logo">
<a href="https://sling.apache.org">
<img border="0" alt="Apache Sling" src="/res/logos/sling.svg"/>
</a>
</div><div class="header">
<a href="https://www.apache.org">
<img border="0" alt="Apache" src="/res/logos/apache.png"/>
</a>
</div>
</div><section class="searchbox level is-marginless">
<div id="searchbox"></div>
</section><div class="columns is-gapless">
<div class="column is-narrow sidemenu">
<div class="container">
<nav class="menu">
<ul class="menu-list box is-shadowless is-marginless">
<li>
<p class="menu-label">
<strong>Documentation</strong>
</p><ul>
<li><a href="/documentation.html">Overview</a></li><li><a href="/documentation/getting-started.html">Getting Started</a></li><li><a href="/documentation/the-sling-engine.html">The Sling Engine</a></li><li><a href="/documentation/development.html">Development</a></li><li><a href="/documentation/bundles.html">Bundles</a></li><li><a href="/documentation/tutorials-how-tos.html">Tutorials &amp; How-Tos</a></li><li><a href="/components/">Maven Plugins</a></li><li><a href="/documentation/configuration.html">Configuration</a></li>
</ul>
</li><li>
<p class="menu-label">
<strong>API Docs</strong>
</p><ul>
<li><a href="/apidocs/sling12/index.html">Sling 12</a></li><li><a href="/apidocs/sling11/index.html">Sling 11</a></li><li><a href="/apidocs/sling10/index.html">Sling 10</a></li><li><a href="/apidocs/sling9/index.html">Sling 9</a></li><li><a href="/documentation/apidocs.html">All versions</a></li>
</ul>
</li><li>
<p class="menu-label">
<strong>Support</strong>
</p><ul>
<li><a href="https://s.apache.org/sling.wiki">Wiki</a></li><li><a href="https://s.apache.org/sling.faq">FAQ</a></li><li><a href="/sitemap.html">Sitemap</a></li>
</ul>
</li><li>
<p class="menu-label">
<strong>Project Info</strong>
</p><ul>
<li><a href="/downloads.cgi">Downloads</a></li><li><a href="https://www.apache.org/licenses/">License</a></li><li><a href="/news.html">News</a></li><li><a href="/releases.html">Releases</a></li><li><a href="https://issues.apache.org/jira/browse/SLING">Issue Tracker</a></li><li><a href="/links.html">Links</a></li><li><a href="/contributing.html">Contributing</a></li><li><a href="/project-information.html">Project Information</a></li><li><a href="/project-information/security.html">Security</a></li>
</ul>
</li><li>
<p class="menu-label">
<strong>Source</strong>
</p><ul>
<li><a href="/repolist.html">Repositories</a></li><li><a href="https://gitbox.apache.org/repos/asf?s=sling">Git at Apache</a></li>
</ul>
</li><li>
<p class="menu-label">
<strong>Apache Software<br>Foundation</strong>
</p><ul>
<li><a href="https://www.apache.org/foundation/thanks.html">Thanks!</a></li><li><a href="https://www.apache.org/foundation/sponsorship.html">Become a Sponsor</a></li><li><a href="https://www.apache.org/foundation/buy_stuff.html">Buy Stuff</a></li>
</ul>
</li><li>
<a class="acevent" data-format="square" data-event="random"></a>
</li><li>
<a href="https://apache.org/foundation/contributing.html" class="column">
<img border="0" alt="Support the Apache Software Foundation!" src="/res/images/SupportApache-small.png" width="125"/>
</a>
</li>
</ul>
</nav>
</div>
</div><div class="column main">
<div class="box is-shadowless is-marginless">
<div class="level">
<div class="pagenav">
<div class="breadcrumb">
<ul>
<li>
<a href="/">
Home
</a>
</li><li>
<a href="/documentation.html">
Documentation
</a>
</li><li>
<a href="/documentation/development.html">
Development
</a>
</li>
</ul>
</div>
</div><div class="tags">
<span class="tag">
<a href="/tags/development.html">
development
</a>
</span><span class="tag">
<a href="/tags/mocks.html">
mocks
</a>
</span>
</div>
</div><h1 class="title">
Sling Mocks
</h1><nav class="menu">
<ul class="menu-list box is-shadowless is-paddingless">
<li id="generatedToC">
<p class="menu-label">
<strong>Table of Contents</strong>
</p>
</li>
</ul>
</nav><script src='/res/jquery-3.2.1.min.js' type='text/javascript'></script><script src='/res/tocjs-1-1-2.js' type='text/javascript'></script><script type='text/javascript'>$(document).ready(function() { $('#generatedToC').toc({'selector':'h1[class!=title],h2,h3','ulClass':'menu-list'}); } );</script><div class="content is-marginless">
<div class="row" data-pagefind-body="true"><div><section><p>Mock implementation of selected Sling APIs for easier testing.</p>
<p><!-- TODO reactivate TOC once JBake moves to flexmark-java -->
</p>
<h2><a href="#maven-dependency" id="maven-dependency">Maven Dependency</a></h2>
<p>For JUnit 5:</p>
<pre><code><!-- TODO syntax marker (#!xml) disabled -->&lt;dependency&gt;
&lt;groupId&gt;org.apache.sling&lt;/groupId&gt;
&lt;artifactId&gt;org.apache.sling.testing.sling-mock.junit5&lt;/artifactId&gt;
&lt;/dependency&gt;
</code></pre>
<p>For JUnit 4:</p>
<pre><code><!-- TODO syntax marker (#!xml) disabled -->&lt;dependency&gt;
&lt;groupId&gt;org.apache.sling&lt;/groupId&gt;
&lt;artifactId&gt;org.apache.sling.testing.sling-mock.junit4&lt;/artifactId&gt;
&lt;/dependency&gt;
</code></pre>
<p>See latest version on the <a href="/downloads.cgi">downloads page</a>.</p>
<p>There are three major version ranges available:</p>
<ul>
<li>sling-mock 1.x: compatible with older Sling versions from 2014 (Sling API 2.4 and above), JUnit 4</li>
<li>sling-mock 2.x: compatible with Sling versions from 2016 (Sling API 2.11 and above), since 2.4.0 with Sling versions from 2017 (Sling API 2.16.2 and above, <a href="https://issues.apache.org/jira/browse/SLING-8978">SLING-8978</a>), JUnit 4 and JUnit 5</li>
<li>sling-mock 3.x: compatible with Sling versions from 2018 (Sling API 2.16.4 and above, <a href="https://issues.apache.org/jira/browse/SLING-10045">SLING-10045</a>), JUnit 4 and JUnit 5</li>
</ul>
<h2><a href="#implemented-mock-features" id="implemented-mock-features">Implemented mock features</a></h2>
<p>The mock implementation supports:</p>
<ul>
<li><code>ResourceResolver</code> implementation for reading and writing resource data using the Sling Resource API
<ul>
<li>Backed by a <a href="/documentation/development/jcr-mock.html">mocked</a> or real Jackrabbit JCR implementation</li>
<li>Uses the productive <a href="https://github.com/apache/sling-org-apache-sling-jcr-resource">Sling JCR resource provider implementation</a> internally to do the Resource-JCR mapping</li>
<li>Alternatively the non-JCR mock implementation provided by the <a href="/documentation/development/resourceresolver-mock.html">Sling resourceresolver-mock implementation</a> can be used</li>
</ul>
</li>
<li><code>AdapterManager</code> implementation for registering adapter factories and resolving adaptions
<ul>
<li>The implementation is thread-safe so it can be used in parallel running unit tests</li>
</ul>
</li>
<li><code>SlingScriptHelper</code> implementation providing access to mocked request/response objects and supports getting OSGi services from the <a href="/documentation/development/osgi-mock.html">mocked OSGi</a> environment.</li>
<li>Implementations of the servlet-related Sling API classes like <code>SlingHttpServletRequest</code> and <code>SlingHttpServletRequest</code>
<ul>
<li>It is possible to set request data to simulate a certain Sling HTTP request</li>
</ul>
</li>
<li>Support for Sling Models (Sling Models API 1.1 and Impl 1.1 or higher required), all relevant Sling Models services are registered by default</li>
<li>Additional services: <code>MimeTypeService</code></li>
<li>Context Plugins</li>
</ul>
<p>The following features are <em>not supported</em>:</p>
<ul>
<li>It is not possible (nor intended) to really execute sling components/scripts and render their results.
<ul>
<li>The goal is to test supporting classes in Sling context, not the sling components/scripts themselves</li>
</ul>
</li>
</ul>
<h3><a href="#additional-features" id="additional-features">Additional features</a></h3>
<p>Additional features provided:</p>
<ul>
<li><code>SlingContext</code> JUnit Rule for easily setting up a Sling Mock environment in your JUnit test cases</li>
<li><code>ContentLoader</code> supports importing JSON data and binary data into the mock resource hierarchy to easily prepare a test fixture consisting of a hierarchy of resources and properties.
<ul>
<li>The same JSON format can be used that is provided by the Sling GET servlet for output</li>
</ul>
</li>
<li><code>ContentBuilder</code> and <code>ResourceBuilder</code> make it easier to create resources and properties as test fixture</li>
</ul>
<h2><a href="#usage" id="usage">Usage</a></h2>
<p>The <code>SlingContext</code> object provides access to mock implementations of:</p>
<ul>
<li>OSGi Component Context</li>
<li>OSGi Bundle Context</li>
<li>Sling Resource Resolver</li>
<li>Sling Request</li>
<li>Sling Response</li>
<li>Sling Script Helper</li>
</ul>
<p>Additionally it supports:</p>
<ul>
<li>Registering OSGi services</li>
<li>Registering adapter factories</li>
<li>Accessing ContentLoader, and ContentBuilder and ResourceBuilder</li>
</ul>
<h3><a href="#junit-5-sling-context-junit-extension" id="junit-5-sling-context-junit-extension">JUnit 5: Sling Context JUnit Extension</a></h3>
<p>The Sling mock context can be injected into a JUnit test using a custom JUnit extension named <code>SlingContextExtension</code>. This extension takes care of all initialization and cleanup tasks required to make sure all unit tests can run independently (and in parallel, if required).</p>
<p>Example:</p>
<pre><code><!-- TODO syntax marker (#!java) disabled -->@ExtendWith(SlingContextExtension.class)
public class ExampleTest {
private final SlingContext context = new SlingContext();
@Test
public void testSomething() {
Resource resource = context.resourceResolver().getResource(&quot;/content/sample/en&quot;);
// further testing
}
}
</code></pre>
<p>It is possible to combine such a unit test with a <code>@ExtendWith</code> annotation e.g. for <a href="https://www.javadoc.io/page/org.mockito/mockito-junit-jupiter/latest/org/mockito/junit/jupiter/MockitoExtension.html">Mockito JUnit Jupiter Extension</a>.</p>
<p>The SlingContext has to be defined as non-static field in combination with <code>@BeforeEach</code> and <code>@AfterEach</code> methods if you want to execute setup or tear down code for each test run. It is not supported to use a static field with <code>@BeforeAll</code> and <code>@AfterAll</code> methods. You should never try to instantiate a SlingContext object within a <code>@BeforeEach</code> method, this may lead to duplicate context instances.</p>
<h3><a href="#junit-4-sling-context-junit-rule" id="junit-4-sling-context-junit-rule">JUnit 4: Sling Context JUnit Rule</a></h3>
<p>The Sling mock context can be injected into a JUnit test using a custom JUnit rule named <code>SlingContext</code>. This rule takes care of all initialization and cleanup tasks required to make sure all unit tests can run independently (and in parallel, if required).</p>
<p>Example:</p>
<pre><code><!-- TODO syntax marker (#!java) disabled -->public class ExampleTest {
@Rule
public final SlingContext context = new SlingContext();
@Test
public void testSomething() {
Resource resource = context.resourceResolver().getResource(&quot;/content/sample/en&quot;);
// further testing
}
}
</code></pre>
<p>It is possible to combine such a unit test with a <code>@RunWith</code> annotation e.g. for <a href="https://www.javadoc.io/page/org.mockito/mockito-core/latest/org/mockito/junit/MockitoJUnitRunner.html">Mockito JUnit Runner</a>.</p>
<h3><a href="#choosing-resource-resolver-mock-type" id="choosing-resource-resolver-mock-type">Choosing Resource Resolver Mock Type</a></h3>
<p>The Sling mock context supports different resource resolver types. Example:</p>
<pre><code><!-- TODO syntax marker (#!java) disabled -->public final SlingContext context = new SlingContext(ResourceResolverType.RESOURCERESOLVER_MOCK);
</code></pre>
<p>Different resource resolver mock types are supported with pros and cons, see next chapter for details.</p>
<h3><a href="#resource-resolver-types" id="resource-resolver-types">Resource Resolver Types</a></h3>
<p>The Sling Mocks resource resolver implementation supports different &quot;types&quot; 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.</p>
<p>Resource resolver types currently supported:</p>
<p><strong>RESOURCERESOLVER_MOCK</strong> (default)</p>
<ul>
<li>Simulates an In-Memory resource tree, does not provide adaptions to JCR API.</li>
<li>Based on the <a href="/documentation/development/resourceresolver-mock.html">Sling resourceresolver-mock implementation</a> implementation.</li>
<li>You can use it to make sure the code you want to test does not contain references to JCR API.</li>
<li>Behaves slightly different from JCR resource mapping e.g. handling binary and date values.</li>
<li>This resource resolver type is very fast because data is stored in memory and no JCR mapping is applied.</li>
</ul>
<p><strong>RESOURCEPROVIDER_MOCK</strong></p>
<ul>
<li>Same as RESOURCERESOLVER_MOCK, but uses the productive <a href="https://github.com/apache/sling-org-apache-sling-resourceresolver">Sling Resource Resolver implementation</a> with a mocked resource provider implementation</li>
<li>Allows using multiple resource providers and loading folders for JSON or FileVault XML content.</li>
<li>This resource resolver type is still quite fast, but has a bit more overhead than RESOURCERESOLVER_MOCK.</li>
</ul>
<p><strong>JCR_MOCK</strong></p>
<ul>
<li>Based on the <a href="/documentation/development/jcr-mock.html">JCR Mocks</a> implementation.</li>
<li>Uses the productive <a href="https://github.com/apache/sling-org-apache-sling-jcr-resource">Sling JCR resource provider implementation</a> internally to do the Resource-JCR mapping.</li>
<li>Is quite fast because data is stored only in-memory.</li>
</ul>
<p><strong>NONE</strong></p>
<ul>
<li>Uses the productive <a href="https://github.com/apache/sling-org-apache-sling-resourceresolver">Sling Resource Resolver implementation</a> without any ResourceProvider. You have to register one yourself to do anything useful with it.</li>
<li>The performance of this resource resolver type depends on the resource provider registered.</li>
<li>This is useful if you want to test your own resource provides mapped to root without any JCR.</li>
</ul>
<p><strong>JCR_OAK</strong></p>
<ul>
<li>Uses a real JCR Jackrabbit Oak implementation based on the <code>MemoryNodeStore</code>.</li>
<li>Full JCR/Sling features supported e.g. observations manager, transactions, versioning.</li>
<li>Uses the productive <a href="https://github.com/apache/sling-org-apache-sling-jcr-resource">Sling JCR resource provider implementation</a> internally to do the Resource-JCR mapping.</li>
<li>Takes some seconds for startup on the first access.</li>
<li>Node types defined in OSGi bundle header 'Sling-Nodetypes' found in MANIFEST.MF files in the classpath are registered automatically.</li>
<li>Lucene indexing is not included, thus fulltext search queries will return no result.</li>
</ul>
<p>To use this type you have to declare an additional dependency in your test project:</p>
<pre><code><!-- TODO syntax marker (#!xml) disabled -->&lt;dependency&gt;
&lt;groupId&gt;org.apache.sling&lt;/groupId&gt;
&lt;artifactId&gt;org.apache.sling.testing.sling-mock-oak&lt;/artifactId&gt;
&lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;
</code></pre>
<p>See latest version on the <a href="/downloads.cgi">downloads page</a>.</p>
<h3><a href="#sling-resource-resolver" id="sling-resource-resolver">Sling Resource Resolver</a></h3>
<p>Example:</p>
<pre><code><!-- TODO syntax marker (#!java) disabled -->// 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);
</code></pre>
<p>If you use the <code>SlingContext</code> JUnit rule you case just use <code>context.resourceResolver()</code>.</p>
<h3><a href="#sling-models" id="sling-models">Sling Models</a></h3>
<p>You should use the following approach to test Sling Models.</p>
<h4><a href="#model-registration" id="model-registration">Model Registration</a></h4>
<p>First you need to make sure that the model you want to test is registered. Since Sling Mocks 1.9.0/2.2.0 the Sling Models from the classpath are automatically registered (<a href="https://issues.apache.org/jira/browse/SLING-6363">SLING-6363</a>) when the Manifest contains the right bundle headers (<code>Sling-Model-Packages</code> or <code>Sling-Model-Classes</code>). This behaviour can be tweaked since version 2.2.20 with the <code>SlingContextBuilder.registerSlingModelsFromClassPath(false)</code> method (<a href="https://issues.apache.org/jira/browse/SLING-7712">SLING-7712</a>).</p>
<p>Manual registration is supported via <code>SlingContext.addModelsForPackage(...)</code> and <code>SlingContext.addModelsForClasses(...)</code>.</p>
<h4><a href="#model-instantiation" id="model-instantiation">Model Instantiation</a></h4>
<p>Preferably use the <code>ModelFactory.createModel(...)</code> method rather than the adaptTo method to benefit from better error messages in case of errors.</p>
<pre><code><!-- TODO syntax marker (#!java) disabled -->// load some content into the mocked repo
context.load().json(..., &quot;/resource1&quot;);
// load resource
Resource myResource = content.resourceResolver().getResource(&quot;/resource1&quot;);
// instantiate Sling Model (adaptable via Resource)
// this will throw exceptions if model cannot be instantiated
MyModel myModel = context.getService(ModelFactory.class).createModel(myResource, MyModel.class);
</code></pre>
<h3><a href="#adapter-factories" id="adapter-factories">Adapter Factories</a></h3>
<p>You can register your own or existing adapter factories to support adaptions e.g. for classes extending <code>SlingAdaptable</code>.</p>
<p>Example:</p>
<pre><code><!-- TODO syntax marker (#!java) disabled -->// 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();
</code></pre>
<p>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 <code>SlingContext</code> JUnit rule this is done automatically for you.</p>
<p>If you use the <code>SlingContext</code> JUnit rule you case just use <code>context.registerService()</code>.</p>
<h3><a href="#slingscripthelper" id="slingscripthelper">SlingScriptHelper</a></h3>
<p>Example:</p>
<pre><code><!-- TODO syntax marker (#!java) disabled -->// get script helper
SlingScriptHelper scriptHelper = MockSling.newSlingScriptHelper();
// get request
SlingHttpServletRequest request = scriptHelper.getRequest();
// get service
MyService object = scriptHelper.getService(MyService.class);
</code></pre>
<p>To support getting OSGi services you have to register them via the <code>BundleContext</code> interface of the <a href="/documentation/development/jcr-mock.html">JCR Mocks</a> before. You can use an alternative factory method for the <code>SlingScriptHelper</code> providing existing instances of request, response and bundle context.</p>
<p>If you use the <code>SlingContext</code> JUnit rule you case just use <code>context.slingScriptHelper()</code>.</p>
<h3><a href="#slinghttpservletrequest" id="slinghttpservletrequest">SlingHttpServletRequest</a></h3>
<p>Example for preparing a sling request with custom request data:</p>
<pre><code><!-- TODO syntax marker (#!java) disabled -->// prepare sling request
ResourceResolver resourceResolver = MockSling.newResourceResolver();
MockSlingHttpServletRequest request = new MockSlingHttpServletRequest(resourceResolver);
// simulate query string
request.setQueryString(&quot;param1=aaa&amp;param2=bbb&quot;);
// alternative - set query parameters as map
request.setParameterMap(ImmutableMap.&lt;String,Object&gt;builder()
.put(&quot;param1&quot;, &quot;aaa&quot;)
.put(&quot;param2&quot;, &quot;bbb&quot;)
.build());
// set current resource
request.setResource(resourceResolver.getResource(&quot;/content/sample&quot;));
// set sling request path info properties
MockRequestPathInfo requestPathInfo = (MockRequestPathInfo)request.getRequestPathInfo();
requestPathInfo.setSelectorString(&quot;selector1.selector2&quot;);
requestPathInfo.setExtension(&quot;html&quot;);
// set method
request.setMethod(HttpConstants.METHOD_POST);
// set attributes
request.setAttribute(&quot;attr1&quot;, &quot;value1&quot;);
// set headers
request.addHeader(&quot;header1&quot;, &quot;value1&quot;);
// set cookies
request.addCookie(new Cookie(&quot;cookie1&quot;, &quot;value1&quot;));
</code></pre>
<h3><a href="#slinghttpservletresponse" id="slinghttpservletresponse">SlingHttpServletResponse</a></h3>
<p>Example for preparing a sling response which can collect the data that was written to it:</p>
<pre><code><!-- TODO syntax marker (#!java) disabled -->// 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(&quot;text/plain;charset=UTF-8&quot;, response.getContentType());
assertEquals(CharEncoding.UTF_8, response.getCharacterEncoding());
assertEquals(55, response.getContentLength());
// validate headers
assertTrue(response.containsHeader(&quot;header1&quot;));
assertEquals(&quot;5&quot;, response.getHeader(&quot;header2&quot;));
// validate response body as string
assertEquals(TEST_CONTENT, response.getOutputAsString());
// validate response body as binary data
assertArrayEquals(TEST_DATA, response.getOutput());
</code></pre>
<h3><a href="#import-resource-data-from-json-file-in-classpath" id="import-resource-data-from-json-file-in-classpath">Import resource data from JSON file in classpath</a></h3>
<p>With the <code>ContentLoader</code> 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.</p>
<p>Example JSON data:</p>
<pre><code>{
&quot;jcr:primaryType&quot;: &quot;app:Page&quot;,
&quot;jcr:content&quot;: {
&quot;jcr:primaryType&quot;: &quot;app:PageContent&quot;,
&quot;jcr:title&quot;: &quot;English&quot;,
&quot;app:template&quot;: &quot;/apps/sample/templates/homepage&quot;,
&quot;sling:resourceType&quot;: &quot;sample/components/homepage&quot;,
&quot;jcr:createdBy&quot;: &quot;admin&quot;,
&quot;jcr:created&quot;: &quot;Thu Aug 07 2014 16:32:59 GMT+0200&quot;,
&quot;par&quot;: {
&quot;jcr:primaryType&quot;: &quot;nt:unstructured&quot;,
&quot;sling:resourceType&quot;: &quot;foundation/components/parsys&quot;,
&quot;colctrl&quot;: {
&quot;jcr:primaryType&quot;: &quot;nt:unstructured&quot;,
&quot;layout&quot;: &quot;2;colctrl-lt0&quot;,
&quot;sling:resourceType&quot;: &quot;foundation/components/parsys/colctrl&quot;
}
}
}
}
</code></pre>
<p>Example code to import the JSON data:</p>
<pre><code><!-- TODO syntax marker (#!java) disabled -->context.load().json(&quot;/sample-data.json&quot;, &quot;/content/sample/en&quot;);
</code></pre>
<p>This codes creates a new resource at <code>/content/sample/en</code> (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.</p>
<h3><a href="#import-binary-data-from-file-in-classpath" id="import-binary-data-from-file-in-classpath">Import binary data from file in classpath</a></h3>
<p>With the <code>ContentLoader</code> 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.</p>
<p>Example code to import a binary file:</p>
<pre><code><!-- TODO syntax marker (#!java) disabled -->context.load().binaryFile(&quot;/sample-file.gif&quot;, &quot;/content/binary/sample-file.gif&quot;);
</code></pre>
<p>This codes creates a new resource at <code>/content/binary/sample-file.gif</code> (and - if not existent - the parent resources) and imports the binary data to a jcr:content subnode.</p>
<h3><a href="#building-content" id="building-content">Building content</a></h3>
<p>Sling Mocks provides two alterantives for quickly building test content in the repository with as few code as possible. Sling Mocks provides two alternatives. Both are quite similar in their results, but follow different API concepts. You can choose whatever matches your needs and mix them as well.</p>
<ul>
<li><code>ContentBuilder</code>: Part of Sling Mocks since its first release. If you need a references to each created resource this is the easiest way.</li>
<li><code>ResourceBuilder</code>: Separate bundle that can also be used in integration tests or live instances. Supports a &quot;fluent&quot; API to create a bunch of resources in hierarchy at once.</li>
</ul>
<h4><a href="#building-content-using-contentbuilder" id="building-content-using-contentbuilder">Building content using <code>ContentBuilder</code></a></h4>
<p>The entry point for the <code>ContentBuilder</code> is the <code>create()</code> method on the Sling context.</p>
<p>Example:</p>
<pre><code><!-- TODO syntax marker (#!java) disabled -->context.create().resource(&quot;/content/test1&quot;, ImmutableMap.&lt;String, Object&gt;builder()
.put(&quot;prop1&quot;, &quot;value1&quot;)
.put(&quot;prop2&quot;, &quot;value2&quot;)
.build());
</code></pre>
<p>Simplified syntax without using a map:</p>
<pre><code><!-- TODO syntax marker (#!java) disabled -->context.create().resource(&quot;/content/test1&quot;,
&quot;prop1&quot;, &quot;value1&quot;,
&quot;prop2&quot;, &quot;value2&quot;);
</code></pre>
<p>If you use the <code>SlingContext</code> JUnit rule you case just use <code>context.create()</code>.</p>
<h4><a href="#building-content-using-resourcebuilder" id="building-content-using-resourcebuilder">Building content using <code>ResourceBuilder</code></a></h4>
<p>The entry point for the <code>ResourceBuilder</code> is the <code>build()</code> method on the Sling context.</p>
<p>Example:</p>
<pre><code><!-- TODO syntax marker (#!java) disabled -->context.build().resource(&quot;/content/test1&quot;)
.siblingsMode()
.resource(&quot;test1.1&quot;, &quot;stringParam&quot;, &quot;configValue1.1&quot;)
.resource(&quot;test1.2&quot;, &quot;stringParam&quot;, &quot;configValue1.2&quot;)
.resource(&quot;test1.2&quot;, &quot;stringParam&quot;, &quot;configValue1.3&quot;);
</code></pre>
<p>See JavaDocs of the class <code>org.apache.sling.resourcebuilder.api.ResourceBuilder</code> for a detailed documentation.</p>
<h3><a href="#context-plugins" id="context-plugins">Context Plugins</a></h3>
<p>Sling Mocks supports &quot;Context Plugins&quot; that hook into the lifecycle of each test run and can prepare test setup before or after the other setUp actions, and execute test tear down code before or after the other tearDown action.</p>
<p>To define a plugin implement the <code>org.apache.sling.testing.mock.osgi.context.ContextPlugin&lt;SlingContextImpl&gt;</code> interface. For convenience it is recommended to extend the abstract class <code>org.apache.sling.testing.mock.osgi.context.AbstractContextPlugin&lt;SlingContextImpl&gt;</code>. These plugins can be used with Sling Mock context, but also with context instances deriving from it like AEM Mocks. In most cases you would just override the <code>afterSetUp</code> method. In this method you can register additional OSGi services or do other preparation work. It is recommended to define a constant pointing to a singleton of a plugin instance for using it.</p>
<p>To use a plugin in your unit test class, use the <code>SlingContextBuilder</code> class instead of directly instantiating the <code>SlingContext</code>class. This allows you in a fluent style to configure more options, with the <code>plugin(...)</code> method you can add one or more plugins.</p>
<p>Example:</p>
<pre><code><!-- TODO syntax marker (#!java) disabled -->SlingContext context = new SlingContextBuilder().plugin(MY_PLUGIN).build();
</code></pre>
<p>More examples:</p>
<ul>
<li><a href="https://github.com/apache/sling-org-apache-sling-testing-caconfig-mock-plugin/blob/master/src/main/java/org/apache/sling/testing/mock/caconfig/ContextPlugins.java">Apache Sling Context-Aware Configuration Mock Plugin</a></li>
<li><a href="https://github.com/apache/sling-org-apache-sling-testing-caconfig-mock-plugin/blob/master/src/test/java/org/apache/sling/testing/mock/caconfig/ContextPluginsTest.java">Apache Sling Context-Aware Configuration Mock Plugin Test</a></li>
</ul>
</section></div></div><div data-pagefind-body="true" data-pagefind-weight="7.0" style="display:none;"> - ( Sling Mocks )</div>
</div>
</div>
</div>
</div><footer class="footer">
<div class="content has-text-centered is-small">
<div class="editpagelink">
This page can be edited on GitHub at <a href="https://github.com/apache/sling-site/edit/master/src/main/jbake/content/documentation/development/sling-mock.md">
content/documentation/development/sling-mock.md
</a>
</div> <div class="revisionInfo">
Last modified by <span class="author">Stefan Seifert</span> on <span class="comment">2024-04-22</span>
</div><p>
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.
</p><p>
Copyright © 2007-2024<a href="https://www.apache.org/">
The Apache Software Foundation
</a>|<a href="https://privacy.apache.org/policies/privacy-policy-public.html">
Privacy Policy
</a>
</p>
</div>
</footer>
</div>
</body>
</html>