JUnit 4: AEM Sling Models Unit Test Constructor Injection Example

In this example, we will take a look at how we can mock Sling Model Constructor Injection dependencies for a JUnit 4 Unit test.

Scenario:
The Sling Model must expose either the PROD_URL or the DEAFULT_URL endpoint based on the run mode or request parameters; this is the requirement. The example below will demonstrate the implementation of logic utilising Sling Model Constructor injection, show Unit test examples, and how mocked dependencies can be Sling Model Constructor injected during the test phase. This completes the example.

Technologies here used are:

  • AEM project archetype 19 (link)
  • Mockito 2.27.0 (link)
  • AEM Mocks JUnit 4 2.7.2 (link)

This example uses the AEM project archetype 19 to generate a new AEM project, Junit 4 will be used as the testing framework, Mockito 2.27.0 will be used as the mocking framework, and AEM Mocks will be used to mock AEM objects and AEM objects.

What’s really great about the latest versions of AEM mocks, is that the setup is very minimal. After spinning up a new AEM project from the AEM project archetype 19, you simply need to include the AEM Mocks dependency, and you are ready to go!

Dependencies

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
// pom.xml
<!-- Maven Surefire Plugin -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.20</version>
    <configuration>
        <junitArtifactName>junit:junit:4</junitArtifactName>
    </configuration>
</plugin>
...
<dependencies>
    ...
    <dependency>
        <groupId>io.wcm</groupId>
        <artifactId>io.wcm.testing.aem-mock</artifactId>
        <version>2.7.2</version>
        <scope>test</scope>
    </dependency>
    ...
</dependencies>

// core/pom.xml
<dependencies>
    ...
    <dependency>
        <groupId>io.wcm</groupId>
        <artifactId>io.wcm.testing.aem-mock</artifactId>
    </dependency>
    ...
</dependencies>

Sling Model Test Class : ConstructorInjection.class

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
33
34
35
36
37
38
39
40
41
package com.sourcedcode.core.models;

import com.adobe.cq.export.json.ExporterConstants;
import lombok.Getter;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
import org.apache.sling.models.annotations.Exporter;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.OSGiService;
import org.apache.sling.models.annotations.injectorspecific.SlingObject;
import org.apache.sling.settings.SlingSettingsService;

import javax.inject.Inject;
import javax.inject.Named;

import static org.apache.commons.lang3.StringUtils.EMPTY;
import static org.apache.commons.lang3.StringUtils.isNotEmpty;

@Model(adaptables = {SlingHttpServletRequest.class, Resource.class}, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
@Exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, extensions = ExporterConstants.SLING_MODEL_EXTENSION)
public class ConstructorInjection {

    protected static final String API_URL_PROD = "https://api.sourcedcode.com/v1/constructors";
    protected static final String API_URL_DEFAULT = "https://uat-api.sourcedcode.com/v1/constructors";

    @Getter
    private String apiUrl = EMPTY;

    @Inject
    public ConstructorInjection(@OSGiService @Named("slingSettingsService") final SlingSettingsService slingSettingsService,
                                @SlingObject @Named("slingHttpServletRequest") final SlingHttpServletRequest request) {
        boolean isProd = slingSettingsService.getRunModes().contains("prod");
        boolean isParamProd = isNotEmpty(request.getParameter("prod")) && request.getParameter("prod").equals("true");
        if (isProd || isParamProd) {
            apiUrl = API_URL_PROD;
        } else {
            apiUrl = API_URL_DEFAULT;
        }
    }
}

Sling Model Test Class : ConstructorInjectionTest.class

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package com.sourcedcode.core.models;

import io.wcm.testing.mock.aem.junit.AemContext;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.settings.SlingSettingsService;
import org.apache.sling.testing.mock.sling.ResourceResolverType;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

import java.util.Collections;

import static org.junit.Assert.assertEquals;
import static uk.co.whitbread.wlrestaurants.core.models.ConstructorInjection.API_URL_DEFAULT;
import static uk.co.whitbread.wlrestaurants.core.models.ConstructorInjection.API_URL_PROD;

@RunWith(MockitoJUnitRunner.class)
public class ConstructorInjectionTest {

    @Rule
    public final AemContext context = new AemContext(ResourceResolverType.JCR_MOCK);

    @Mock
    private SlingSettingsService slingSettingsService;

    @Mock
    SlingHttpServletRequest request;

    @InjectMocks
    private ConstructorInjection underTest;

    @Test
    public void apiUrl_should_return_PROD_url_when_runmode_prod() {
        context.runMode("prod");
        underTest = context.request().adaptTo(ConstructorInjection.class);
        assert underTest != null;
        assertEquals(API_URL_PROD, underTest.getApiUrl());
    }

    @Test
    public void apiUrl_should_return_DEFAULT_url_when_runmode_not_prod() {
        context.runMode("staging");
        underTest = context.request().adaptTo(ConstructorInjection.class);
        assert underTest != null;
        assertEquals(API_URL_DEFAULT, underTest.getApiUrl());
    }

    @Test
    public void apiUrl_should_return_PROD_url_when_param_prod_equals_true() {
        context.request().setParameterMap(Collections.singletonMap("prod", "true"));
        underTest = context.request().adaptTo(ConstructorInjection.class);
        assert underTest != null;
        assertEquals(API_URL_PROD, underTest.getApiUrl());
    }

    @Test
    public void apiUrl_should_return_DEFAULT_url_when_param_prod_equals_not_true() {
        context.request().setParameterMap(Collections.singletonMap("prod", "test"));
        underTest = context.request().adaptTo(ConstructorInjection.class);
        assert underTest != null;
        assertEquals(API_URL_DEFAULT, underTest.getApiUrl());

    }
}
More…
Click here to view more examples of AEM JUnit 4 Unit Test Examples.

Was this post helpful?

Certified AEM Developer who has been working on AEM software developer for the past 5 years.

Leave a Reply

Your email address will not be published. Required fields are marked *

Back To Top