For AI agents: the complete documentation index is available at https://nhanbe.id.vn/llms.txt, the full documentation bundle is available at https://nhanbe.id.vn/llms-full.txt, and this page is available as Markdown at https://nhanbe.id.vn/aem/foundation/testing-and-debugging.md.

What it cover: Sling Models, services, utility logic in isolation Tooling: JUnit 5, Mockito, wcm.io AEM Mocks (`AEMContext`) `AEMContext` from

Testing and Debugging

Unit Test

  • What it cover: Sling Models, services, utility logic in isolation
  • Tooling: JUnit 5, Mockito, wcm.io AEM Mocks (AEMContext)

Unit Test for Sling Models

AEMContext from io.wcm.mock.aem.junit5 gives an in-memory JCR+Sling+AEM context, so you can register a model, load content, and assert on the result - no running instance required.

import io.wcm.testing.mock.aem.junit5.AemContext;
import io.wcm.testing.mock.aem.junit5.AemContextExtension;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

import static org.junit.jupiter.api.Assertions.assertEquals;

@ExtendWith(AemContextExtension.class)
class HelloModelTest {

    private final AemContext ctx = new AemContext();

    @Test
    void rendersTitle() {
        ctx.addModelsForClasses(HelloModel.class);
        ctx.load().json("/com/mysite/core/models/HelloModel.json", "/content/hello");

        Resource resource = ctx.resourceResolver().getResource("/content/hello");
        HelloModel model = resource.adaptTo(HelloModel.class);

        assertEquals("Hello, World", model.getTitle());
    }
}

Put the fixture JSON under src/test/resources mirroring the package. For a request-adaptable model, use ctx.request() as the adaptable and set ctx.currentResource(...) first.

Mocking OSGi services

Register mocks with Mockito and inject them into the context so ur model's @OSGiService/@Reference dependencies resolve:

MyService svc = mock(MyService.class);
when(svc.compute()).thenReturn("stubbed");
ctx.registerService(MyService.class, svc);

What to unit-test

  • Getter logic, defaults, and null/empty handling.
  • Branching in @PostContruct
  • Any Business rule (formatting, filtering, validation fallbacks)

Code coverage and quality gates

Jacoco

Debugging toolkit

Logs

  • crx-quickstart/log/error.log the primary log.

CRXDE Lite

Confirm a property actually persisted, check sling:resourceType, inspect ACLs.

Request process, recent requets

system/console/requests shows full Sling processing of a request; which script/servlet rendered it, included resources, and timings.

Component and clientlib resolution

  • Append ?debugClientLibs=true to a page to load clientlibs unminified and see exactly which files are included.
  • Use /libs/granite/ui/content/dumplibs.html to inspect clientlib categories and dependencies.
  • The HTL/Sling WCM debug filter (?wcmmode=disabled) renders the page without editing chrome.

JaCoCo Unit Test Coverage

  1. Navigate to your projects root /pom.xml
  2. Add following line to <properties> section
  3. Add JaCoCo Plugin
<plugin>
     <groupId>org.jacoco</groupId>
     <artifactId>jacoco-maven-plugin</artifactId>
     <version>0.8.8</version>
     <executions>
         <execution>
         <id>prepare-and-report</id>
         <goals>
         <goal>prepare-agent</goal>
         <goal>report</goal>
         </goals>
         </execution>
         <execution>
         <id>report-aggregate</id>
         <phase>verify</phase>
         <goals>
         <goal>report-aggregate</goal>
         </goals>
         <configuration>
             <outputDirectory>${project.basedir}/../target/site/jacoco-aggregate</outputDirectory>
             <excludes>
                 <exclude>ui.apps/**/*</exclude>
                 <exclude>ui.tests/**/*</exclude>
                 <exclude>it.tests/**/*</exclude>
             </excludes>
         </configuration>
         </execution>
     </executions>
</plugin>