Hi Team,
I have written jUnit test cases for custom teaser component which extends the core Teaser component using the Delegation Pattern for Sling Models using "@Self @Via(type=ResourceSuperType.class) as specified here: https://github.com/adobe/aem-core-wcm-components/wiki/Delegation-Pattern-for-Sling-Models
Junit coverage is less on environment, in my local it is 100 % I have covered junits for custom methods which written custom teaser model, There are methods in parent class ( below in screenshot ) which does not cover in my custom test class, How to overcome this issue?
Solved! Go to Solution.
Views
Replies
Total Likes
@gskittu Have a getter method which returns Teaser teaser which you have injected @Self and @Via
Just showing an example below you can follow the same pattern while dealing with any delegate slingmodels
Example.class
ExampleTest.java
Hope this helps,
Krishna
@gskittu Have a getter method which returns Teaser teaser which you have injected @Self and @Via
Just showing an example below you can follow the same pattern while dealing with any delegate slingmodels
Example.class
ExampleTest.java
Hope this helps,
Krishna
Thanks you Krishna, There are some more methods which we don't require, With those fields coverage is less, how can we fix this issue
I have below extended from Teaser. I have written JUnit class for this But I see teaser object as null. How did you inject teaser in your JUnit Test class.
Thanks for any help.
custom model class implements Teaser.
@Model(
adaptables = {SlingHttpServletRequest.class},
adapters = {Teaser.class, TargetDateFund.class, ComponentExporter.class},
resourceType = {TargetDateFundImpl.RESOURCE_TYPE},
defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL
)
@Exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME , extensions = ExporterConstants.SLING_MODEL_EXTENSION)
public class TargetDateFundImpl implements TargetDateFund
{
protected static final String RESOURCE_TYPE = "pi-web/components/content/targetdatefund";
@SlingObject
private ResourceResolver resourceResolver;
@Self
@Required
private SlingHttpServletRequest request;
@Self
@Via(type = ResourceSuperType.class)
private com.adobe.cq.wcm.core.components.models.Teaser teaser;
@ScriptVariable
private ValueMap properties;
@Inject
private ModelFactory modelFactory;
@Inject
private SlingModelFilter slingModelFilter;
private String fragmentPath;
private String hedgeText;
private Map<String, ComponentExporter> childModels = null;
@PostConstruct
protected void initModel() {
fragmentPath = properties.get("fragmentPath", String.class);
if (StringUtils.isNotEmpty(fragmentPath)) {
Resource fragmentResource = resourceResolver.getResource(fragmentPath);
if (fragmentResource != null) {
Optional<ContentFragment> contentFragment = Optional.ofNullable(fragmentResource.adaptTo(ContentFragment.class));
hedgeText = contentFragment.map(cf -> cf.getElement("main")).map(ContentElement::getContent)
.orElse(org.apache.commons.lang.StringUtils.EMPTY);
}
}
}
@Override
public String getFragmentPath() {
return fragmentPath;
}
@Override
public String getHedgeText() { return hedgeText; }
/** properties extended from teaser**/
@Override
public boolean isActionsEnabled() {
return teaser.isActionsEnabled();
}
@Override
public List<ListItem> getActions() {
return teaser.getActions();
}
@Override
public Link getLink() {
return teaser.getLink();
}
@Override
public String getLinkURL() {
return teaser.getLinkURL();
}
@Override
public Resource getImageResource() {
return teaser.getImageResource();
}
@Override
public boolean isImageLinkHidden() {
return teaser.isImageLinkHidden();
}
@Override
public String getPretitle() {
return teaser.getPretitle();
}
@Override
public String getTitle() {
return teaser.getTitle();
}
@Override
public boolean isTitleLinkHidden() {
return teaser.isTitleLinkHidden();
}
@Override
public String getDescription() {
return teaser.getDescription();
}
@Override
public String getTitleType() {
return teaser.getTitleType();
}
@Override
public String getId() {
return teaser.getId();
}
@Override
public ComponentData getData() {
return teaser.getData();
}
@Override
public String getAppliedCssClasses() {
return teaser.getAppliedCssClasses();
}
@Override
public String getExportedType() {
return TargetDateFundImpl.RESOURCE_TYPE;
}
@NotNull
@Override
public Map<String, ? extends ComponentExporter> getExportedItems() {
if (childModels == null) {
childModels = getChildModels(request, ComponentExporter.class);
}
return childModels;
}
@NotNull
@Override
public String[] getExportedItemsOrder() {
Map<String, ? extends ComponentExporter> models = getExportedItems();
if (models.isEmpty()) {
return ArrayUtils.EMPTY_STRING_ARRAY;
}
return models.keySet().toArray(ArrayUtils.EMPTY_STRING_ARRAY);
}
/**
* Returns a map (resource name => Sling Model class) of the given resource
* children's Sling Models that can be adapted to {@link T}.
*
* slingRequest the current request
* modelClass the Sling Model class to be adapted to
* a map (resource name => Sling Model class) of the given resource
* children's Sling Models that can be adapted to {@link T}
*/
@NotNull
private <T> Map<String, T> getChildModels(@NotNull SlingHttpServletRequest slingRequest,
Class<T> modelClass) {
Map<String, T> itemWrappers = new LinkedHashMap<>();
for (final Resource child : slingModelFilter.filterChildResources(request.getResource().getChildren())) {
itemWrappers.put(child.getName(), modelFactory.getModelFromWrappedRequest(slingRequest, child, modelClass));
}
return itemWrappers;
}
/** END exptended proeprties **/
}
JUnit
import com.adobe.cq.dam.cfm.ContentElement;
import com.adobe.cq.dam.cfm.ContentFragment;
import com.adobe.cq.wcm.core.components.models.Teaser;
import io.wcm.testing.mock.aem.junit5.AemContext;
import io.wcm.testing.mock.aem.junit5.AemContextExtension;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.models.factory.ModelFactory;
import org.apache.sling.testing.mock.sling.ResourceResolverType;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.logging.Logger;
import static org.junit.jupiter.api.Assertions.*;
@ExtendWith({ AemContextExtension.class, MockitoExtension.class })
class TargetDateFundImplTest {
private final AemContext context = new AemContext(ResourceResolverType.JCR_MOCK);
@InjectMocks
private TargetDateFundImpl targetDateFund;
@Mock
Teaser teaser;
@Mock
private ModelFactory modelFactory;
@BeforeEach
void setUp() {
MockitoAnnotations.initMocks(this);
context.load().json("/components/teaser/test-content.json", "/content");
context.load().json("/dam/content-fragments/simplecf.json", "/content/dam/cfs");
context.currentPage("/content/teasers");
context.currentResource("/content/teasers/jcr:content/root/responsivegrid/teaser-2");
context.registerService(ModelFactory.class, modelFactory);
targetDateFund = context.request().adaptTo(TargetDateFundImpl.class);
}
@test
void getFragmentPath() {
assertNotNull(targetDateFund.getFragmentPath());
}
@test
void getHedgeText() {
assertNotNull(targetDateFund.getHedgeText());
}
}
Views
Replies
Total Likes
Views
Likes
Replies