Unit testing or Junit for Sling models using Mockito in AEM
- First generate AEM sample project with the help of below archetype which will download the sample AEM project compatible in AEM 6.5
mvn -B archetype:generate -D archetypeGroupId=com.adobe.granite.archetypes -D archetypeArtifactId=aem-project-archetype -D archetypeVersion=23 -D aemVersion=cloud -D appTitle="Training" -D appId="training" -D groupId="com.training"-D frontendModule=general -D includeExamples=n
This will generate a project with below structure
Now add the dependency for Mockito
- Add below entry in main pom.xml
- Add below entry to core/pom.xml .
- Create new Sling model class with name 'HelloIndiaModel' which will have Sling Objects such as Resource and ResourceResolver, init method and public method getMessage which will return a message based on few conditions.
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageManager;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.SlingObject;
import javax.annotation.PostConstruct;
import java.util.Optional;
@Model(adaptables = Resource.class)
public class HelloIndiaModel {
@SlingObject
private Resource currentResource;
@SlingObject
private ResourceResolver resourceResolver;
private String message;
@PostConstruct
protected void init() {
PageManager pageManager = resourceResolver.adaptTo(PageManager.class);
String currentPagePath = Optional.ofNullable(pageManager)
.map(pm -> pm.getContainingPage(currentResource))
.map(Page::getPath).orElse("");
message = "Hello " + getRegion(currentPagePath);
}
private String getRegion(String currentPagePath){
if(currentPagePath.contains("geometrixx")){
return "Geometrixx";
}else if(currentPagePath.contains("India")){
return "Indians";
}
else {
return "World";
}
}
public String getMessage() {
return message;
}
}
- Now go to test folder , create test class for HelloIndiaModel, this class should have an annotation @RunWith(MockitoJUnitRunner.class) which keeps tests clean and improves debugging experience.
- Try to understand the logic of init method from HelloIndiaModel, first line is using resourceresolver to adapt to PageManager. Since both of these objects are AEM/Sling Objects so we need to mock these Objects in our HelloIndiaModelTest class
- Line 3 is trying to get the Page from page manager object, Page Object is also belongs to AEM hence we need to mock this object as well
@Mock
private Resource currentResource;
@Mock
private ResourceResolver resourceResolver;
@Mock
private Page currentPage;
@Mock
private PageManager pageManager;
- We have used the @Mock since we need these objects to support testing of class to be tested.
- Now we need to call the Object of the class which we wish to write test, which can be done by . using the @InjectMocks
@InjectMocks
private HelloIndiaModel helloIndiaModel;
- Now we need to handle the logic which is written using sling objects in sling model. For example :- what should mockito do when it reaches to the line resourceResolver.adaptTo(PageManager.class); We can specify this with the help of @Before method.
Methods annotated with the @Before annotation are executed before each test. This is useful when we want to execute some common code before running a test.
public void setUp() {
when(resourceResolver.adaptTo(PageManager.class)).thenReturn(pageManager);
when(pageManager.getContainingPage(currentResource)).thenReturn(currentPage);
when(currentPage.getPath()).thenReturn("/content/geometrixx");
helloIndiaModel.init();
}
- Write first test for the method getMessage
@Test
public void shouldMatch(){
assertNotNull(helloIndiaModel.getMessage());
assertEquals("Hello Geometrixx",helloIndiaModel.getMessage());
}
Please find below the complete Test class
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageManager;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import static junit.framework.Assert.assertNotNull;
import static junitx.framework.Assert.assertEquals;
import static junitx.framework.Assert.assertNotEquals;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class HelloIndiaModelTest {
@Mock
private Resource currentResource;
@Mock
private ResourceResolver resourceResolver;
@Mock
private Page currentPage;
@Mock
private PageManager pageManager;
@InjectMocks
private HelloIndiaModel helloIndiaModel;
//initialize
@Before
public void setUp() {
when(resourceResolver.adaptTo(PageManager.class)).thenReturn(pageManager);
when(pageManager.getContainingPage(currentResource)).thenReturn(currentPage);
when(currentPage.getPath()).thenReturn("/content/geometrixx");
helloIndiaModel.init();
}
@Test
public void shouldNotMatch(){
assertNotNull(helloIndiaModel.getMessage());
assertNotEquals("Hiiiii",helloIndiaModel.getMessage());
}
@Test
public void shouldMatch(){
assertNotNull(helloIndiaModel.getMessage());
assertEquals("Hello Geometrixx",helloIndiaModel.getMessage());
}
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageManager;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import static junit.framework.Assert.assertNotNull;
import static junitx.framework.Assert.assertEquals;
import static junitx.framework.Assert.assertNotEquals;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class HelloIndiaModelTest {
@Mock
private Resource currentResource;
@Mock
private ResourceResolver resourceResolver;
@Mock
private Page currentPage;
@Mock
private PageManager pageManager;
@InjectMocks
private HelloIndiaModel helloIndiaModel;
//initialize
@Before
public void setUp() {
when(resourceResolver.adaptTo(PageManager.class)).thenReturn(pageManager);
when(pageManager.getContainingPage(currentResource)).thenReturn(currentPage);
when(currentPage.getPath()).thenReturn("/content/geometrixx");
helloIndiaModel.init();
}
@Test
public void shouldNotMatch(){
assertNotNull(helloIndiaModel.getMessage());
assertNotEquals("Hiiiii",helloIndiaModel.getMessage());
}
@Test
public void shouldMatch(){
assertNotNull(helloIndiaModel.getMessage());
assertEquals("Hello Geometrixx",helloIndiaModel.getMessage());
}
No comments:
Post a Comment