Basics:
Java file
packages are present in /src/main/java folder, so same package name
should be present in /src/test/java with same file name just append
“Test” in last
Example:
Sample.java
For this
class Test class name should be SampleTest.java
Installation
Instructions:
Step1) Go
here https://www.eclipse.org/downloads/ and click on "Download 64
bit" button, this will download 102 MB eclipse Installer .exe file
Step 2) Run
this Installer .exe it will download eclipse 2020-09 [Latest]
Step 3) Open
Eclipse ->Project -> Properties->Java Build Path -> Add Library
Select Junit and click next, it will populate Junit 5 in Dropdown just
click on finish
Step4) Now
run coverage it works fine
Points to
be noted:
// This
should be used when context object needs to be used
Refer below document for more details
2) For Junit 4: On top of test class name add below annotation
@RunWith(PowerMockRunner.class)
// This can be used for line coverage
public void setUp() throws Exception {
// declare all mock object here
//set all private variable here using PrivateAccessor
// Try to handle all possible logic line here why adding when().thenReturn() to define outputs of it as we want
//create global object of .java class and use it to call all related method of .java class
// to cover all lines coverage
}
@After
public void tearDown() throws Exception {
// If any new global object created for any class here, make them null here.
}
Now for all the public methods defined in
.java class Test method needs to be created with below format
If one of the method name in .java class is getSitemapIndex then create below test method
@Test
public final void testGetSitemapIndex() {
// use any testing method here to compare any variable output from that method
// Example: assertEquals(StringUtils.EMPTY,helperObj.getSitemapIndex());
}
4) If we have used below variables anywhere in class, we can get it from either aem context object
Or we can mock it if using power mock
Variables: slingRequest, slingResponse,
session, resolver, pageManager
When using AEM Context:
private final AemContext context = new AemContext();
private final MockSlingHttpServletRequest request = context.request();
private final MockSlingHttpServletResponse response = context.response();
private final Session session = context.resourceResolver().adaptTo(Session.class);
private final ResourceResolver resResolver = context.resourceResolver();
private final PageManager pageManager = context.pageManager();
- 5) We can mock all objects which ever is used in the .java calls
Few examples:
Resource res = mock(Resource.class);
ValueMap pageProperties = mock(ValueMap.class);
- 6) If any method is called on any object, then it can throw Null Pointer Exception, as it can be null.
So, to handle this scenario, we can set that class
level variables or static objects from Junit itself to avoid Null pointer.
Example:
If we are using resource.getPath(), here it’s
giving Null pointer Exception, we should add below line to avoid it
Resource res = mock(Resource.class);
PrivateAccessor.setField(introductionCopyHelper, "res",
res);
Note: This is used to set
Class level variables or static objects. For local vars, values are often set
as a return value of a method which can be handled by “when” and “thenReturn”.
But can’t do the same for static objects.
- 7) We can use below methods to test code
import static org.junit.Assert.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import io.wcm.testing.mock.aem.junit5.AemContextExtension;
import org.powermock.core.classloader.annotations.PrepareForTest;
import junitx.util.PrivateAccessor;
Page mockPage = mock(Page.class);
when(mockPage.getPath()).thenReturn("/content/www/global/en");
assertEquals("my-static-string", someHelperObj.getMyComponentId());
There are lot more methods available like
assertNull, assertNotNull, assertFalse etc.
You can find all list of available methods in below
API reference document: https://junit.org/junit5/docs/5.0.1/api/org/junit/jupiter/api/Assertions.html
- 8) To set field of any super class, use
below syntax
import java.lang.reflect.Field;
.getSuperclass().getDeclaredField("currentPage");
privateOrProtectedField.setAccessible(true);
privateOrProtectedField.set(contentHelper, mockPage);
9) Handle Static classes
Example: we need to test StringUtils.isNotBlank for below lines of code:
String pageSelectors = slingRequest.getRequestPathInfo().getSelectorString();
if (StringUtils.isNotBlank(pageSelectors)) {
Then handle it like shown below:
String pageSelectors = "Test Page Selector";
when(slingRequest.getRequestPathInfo().getSelectorString()).thenReturn(pageSelectors);
assertTrue(StringUtils.isNotBlank(pageSelectors));
Also, to handle Final class like Locale whose object cannot be created, used below syntax to handle it
import org.apache.commons.lang.LocaleUtils;
Locale locale = LocaleUtils.toLocale("us");
10) If some property check is not working, Debug Junit and check if its coming correct or not.
Sometimes if instance of object is different it does not work or comes as null.
Example:
String templateType = Util.getStringProperty(currentPageProperties, Constants.TEMPLATE_PROP_KEY);
if (StringUtils.isNotBlank(templateType)) {
In this case debug and check template type should not come as null
when(currentPage.getProperties()).thenReturn(currentPageProperties);
assertNotNull(currentPageProperties); when(currentPageProperties.containsKey(Constants.TEMPLATE_PROP_KEY)).thenReturn(true);
when(currentPageProperties.get(Constants.TEMPLATE_PROP_KEY)).thenReturn("Test Template");
when(Util.getStringProperty(currentPageProperties, Constants.TEMPLATE_PROP_KEY))
.thenReturn(templateType);
assertTrue(StringUtils.isNotBlank(templateType));
11) When we want to mock with generic params, whose value can be anything
Eg:
import static org.mockito.ArgumentMatchers.anyMap;
import static org.mockito.ArgumentMatchers.anyString;
when(contComp.prepareQueryParams(anyString(), anyMap())).thenReturn(mockParams);
12) For handling new objects
PowerMockito.whenNew(HierarchyNodeInheritanceValueMap.class).withArguments(mockResource).thenReturn(mockCurrentPageInherited);
13) Scenario where we need to iterate in a loop
For Example we have Java class with below block:
Iterator<Resource> allChildren = resource.getChildren().iterator();
while (allChildren.hasNext()) {
Resource childResource= allChildren.next();
}
Then for this JUnit should be like mentioned below [this will iterate 2 times]
Iterable<Resource> mockIterable = (Iterable<Resource>) mock(Iterable.class);
when(res.getChildren()).thenReturn(mockIterable);
Iterator<Resource> mockIterator = (Iterator<Resource>) mock(Iterator.class);
when(mockIterable.iterator()).thenReturn(mockIterator);
when(mockIterator.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false);
when(mockIterator.next()).thenReturn(res);
14) In case catch block also needs to be covered, this is how exception can be thrown from Junit
when(mockResourceResolver.getResource(mockCurrentPage.getPath())).thenThrow(NullPointerException.class);
For void return type methods throw exception as mentioned below:
import static org.mockito.Mockito.doThrow;
doThrow(new AccessDeniedException()).when(basicSession).save();
15) Mocking parameterized constructor
import static org.powermock.api.mockito.PowerMockito.whenNew;
Second second = Mockito.mock(Second.class);
whenNew(Second.class).withNoArguments().thenReturn(second);
16) Call private method
import org.mockito.MockitoAnnotations;
import java.lang.reflect.Method;
MockitoAnnotations.initMocks(this);
Method postConstruct = MyClass.class.getDeclaredMethod("initModel", null); // methodName,parameters
postConstruct.setAccessible(true);
postConstruct.invoke(myclassObj);
.............................
Also in case its a private constructor then use below code
final Constructor<?>[] constructors = MyClass.class.getDeclaredConstructors();
for (final Constructor<?> constructor : constructors) {
Assert.assertTrue(Modifier.isPrivate(constructor.getModifiers()));
}
constructors[0].setAccessible(true);
// In this case private contructor was parameterized and was having two strings as params
myClassObj= (MyClass) constructors[0].newInstance(TEST_DATA, TEST_DATA);
17) Mock Static class
Put these annotation on top of class name
@RunWith(PowerMockRunner.class)
@PrepareForTest({ MyUtil.class})
Use below lines in method
PowerMockito.mockStatic(MyUtil.class);
when(MyUtil.getURL(redirectPath)).thenReturn("http://www.google.com");
18) If getting any exception in Gson, link any Gson internal class not found then include below dependency in pom to resolve this issue
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.0</version>
</dependency>
19) How to handle SlingQuery $() statements
Example to handle below syntax
SlingQuery slingQuery = $(currentResource).closest("somestring");
Use below Junit code
import org.apache.sling.query.SlingQuery;
@RunWith(PowerMockRunner.class)
@PrepareForTest({ SlingQuery.class })
private SlingQuery slingQuery;
slingQuery = mock(SlingQuery.class);
when(slingQuery.toString()).thenReturn("test-data");
PowerMockito.mockStatic(SlingQuery.class);
when(SlingQuery.$(resource)).thenReturn(slingQuery);
when(slingQuery.closest("test-data")).thenReturn(slingQuery);
No comments:
Post a Comment