Day 22 of 40
WKND: Unit Testing
AEM Mocks, wcm.io, JUnit 5, and what Cloud Manager measures
By the end of today you should be able to
- Write a unit test for a Sling Model using AEM Mocks
- Load test content from JSON into the mock repository
- Explain what Cloud Manager's code quality gate measures
- Distinguish unit tests from integration tests and know where each belongs
What you can actually unit test
Sling Models are ordinary Java, so they are testable — but they depend on a repository, a resource
resolver and request context. AEM Mocks (io.wcm.testing.aem-mock)
provides all of that in-memory. No running AEM, no deployment, tests measured in milliseconds.
This is the one chapter of the WKND tutorial with no Adobe video — it is written and code-only. The notes here carry the weight.
AemContext
The JUnit 5 extension AemContextExtension gives you an AemContext: a mock
Sling environment with a real (in-memory) JCR, a resource resolver, a request and response, and an
OSGi service registry you can populate.
@ExtendWith(AemContextExtension.class)
class BylineImplTest {
private final AemContext ctx = new AemContext();
@BeforeEach
void setUp() {
ctx.addModelsForClasses(BylineImpl.class);
ctx.load().json("/com/adobe/aem/guides/wknd/core/models/BylineImplTest.json",
"/content");
}
@Test
void getName_returnsAuthoredName() {
ctx.currentResource("/content/byline");
Byline byline = ctx.request().adaptTo(Byline.class);
assertNotNull(byline);
assertEquals("Jane Doe", byline.getName());
}
@Test
void isEmpty_whenNoOccupations_returnsTrue() {
ctx.currentResource("/content/empty-byline");
Byline byline = ctx.request().adaptTo(Byline.class);
assertTrue(byline.isEmpty());
}
}
Test content as JSON
ctx.load().json(...) reads a JSON file from the test resources and creates those nodes in
the mock repository. The format mirrors what you would get from
/content/path.infinity.json on a real instance — so the quickest way to build a fixture
is to author the content once, export it, and trim it down.
{
"byline": {
"jcr:primaryType": "nt:unstructured",
"sling:resourceType": "wknd/components/byline",
"name": "Jane Doe",
"occupations": {
"item0": { "occupation": "Writer" },
"item1": { "occupation": "Photographer" }
}
},
"empty-byline": {
"jcr:primaryType": "nt:unstructured",
"sling:resourceType": "wknd/components/byline"
}
}
Mocking services
Where a model depends on an OSGi service, register a Mockito mock into the context:
ExternalService svc = mock(ExternalService.class);
when(svc.lookup("abc")).thenReturn("result");
ctx.registerService(ExternalService.class, svc);
This is also the moment poor design shows up. A model that is hard to test — because it reaches for a dozen services or does I/O in a getter — is usually telling you it is doing too much.
The Cloud Manager quality gate
Cloud Manager runs SonarQube analysis and test coverage on every production pipeline. The rules that matter in practice:
- Line coverage has a threshold (commonly 50%) below which the gate fails.
- Findings are tiered: Critical failures stop the pipeline; Important ones can be overridden by an authorised user with a justification; Info is advisory.
- Security findings and use of deprecated or forbidden APIs are flagged here.
Chasing a percentage produces tests that assert getters return what you set. Test the logic — the branching, the null cases, the sorting, the empty state. A model with real behaviour and three meaningful tests beats one with twelve trivial ones.
Unit vs integration tests
- Unit tests (
core/src/test) — AEM Mocks, no running instance, milliseconds. The bulk of your testing. - Integration tests (
it.tests) — run against a real AEM instance over HTTP. Slower, for things mocks cannot prove: replication, real servlet behaviour, actual rendering. - UI tests (
ui.tests) — Cypress or Selenium against a browser. Slowest, reserved for critical author journeys.
The pyramid applies: many unit tests, some integration tests, few UI tests. Cloud Manager can run all three, and functional test failures will stop a production deployment.
AemContext plus JSON fixtures makes Sling Models genuinely unit-testable. Aim at logic rather than at a coverage number, and keep integration tests for what mocks cannot prove.
No video for this one
Adobe does not publish a video for this chapter — it is written and code-only. The notes above carry the weight today.
Read on Experience League
The primary sources these notes are drawn from.
Your notes
Saved automatically to this browser.
Check yourself
10 questions on today's material. 80% to pass.