unit testing of query, querybuilder, session from resourceresolver | Community
Skip to main content
sreenu539
January 8, 2024
Solved

unit testing of query, querybuilder, session from resourceresolver

  • January 8, 2024
  • 3 replies
  • 3540 views

Hi All,

 

I have set up test content json for below source code.

Is it possible to have a real resource resolver, query builder, query, session to go through test content json get me the results.

 

All the unit-test examples out there on internet talking about mocking  query, querybuilder, session, searchresult, objects and do mockito returns rather than performing real query search on test content json.

 

I am looking to test query in below source code to do real querying on test content json and give results back.

 

I appreciate any help! NOTE: resource resolver that comes with test aemcontext can adapt to pagemanger but not not to querybuilder or serssion.

I would like to know if it is possible or not , if so , any small example would be appreciated.

 

private void getFaqs() { try { QueryBuilder queryBuilder = resourceResolver.adaptTo(QueryBuilder.class); if (queryBuilder == null) { LOG.warn("Query builder was null therefore no query was executed"); return; } if (contentFragmentsList != null) { Map<String, String> cfVariationMap = new HashMap<>(); Map<String, String> queryParameterMap = new HashMap<>(); queryParameterMap.put("type", "dam:AssetContent"); queryParameterMap.put("property", "data/cq:model"); queryParameterMap.put("property.value", "/conf/test-project/simple-model/settings/dam/cfm/models/faq-model"); queryParameterMap.put("group.p.or", "true"); IntStream.range(1, contentFragmentsList.size() + 1) .forEach(faqIndex -> { if (contentFragmentsList.get(faqIndex - 1).getFragmentPath() != null && !contentFragmentsList.get(faqIndex - 1).getFragmentPath().isEmpty()) { queryParameterMap.put("group." + faqIndex + "_group.path", contentFragmentsList.get(faqIndex - 1).getFragmentPath()); if(contentFragmentsList.get(faqIndex - 1).getVariationName() != null && !contentFragmentsList.get(faqIndex - 1).getVariationName().isEmpty()){ cfVariationMap.put(contentFragmentsList.get(faqIndex-1).getFragmentPath(), contentFragmentsList.get(faqIndex-1).getVariationName()); } if (contentFragmentsList.get(faqIndex - 1).getCategory() != null && contentFragmentsList.get(faqIndex - 1).getCategory().length > 0) { queryParameterMap.put("group." + faqIndex + "_group.property.or", "true"); queryParameterMap.put("group." + faqIndex + "_group.property", "data/master/cq:tags"); IntStream.range(1, contentFragmentsList.get(faqIndex - 1).getCategory().length + 1).forEach(tagIndex -> { queryParameterMap.put("group." + faqIndex + "_group.property." + tagIndex + "_value", contentFragmentsList.get(faqIndex - 1).getCategory()[tagIndex - 1]); }); } } }); if ("title".equalsIgnoreCase(orderBy)) { queryParameterMap.put("orderby", "@" + JcrConstants.JCR_TITLE); queryParameterMap.put("orderby.sort", sortOrder); } queryParameterMap.put("p.limit", Integer.toString(100)); LOG.debug("FAQ Query Map: '{}'", queryParameterMap); PredicateGroup predicateGroup = PredicateGroup.create(queryParameterMap); Query query = queryBuilder.createQuery(predicateGroup, resourceResolver.adaptTo(Session.class)); SearchResult searchResult = query.getResult(); faqs = searchResult.getHits().stream() .map(hit -> { try { FAQContentFragment faqCF= Objects.requireNonNull(resourceResolver.resolve(hit.getPath()).getParent()).adaptTo(FAQContentFragment.class); if (faqCF != null) { String cfPath = substringBefore(hit.getPath(), "/jcr:content"); String variationName=cfVariationMap.get(cfPath); if(variationName != null){ faqCF.setVariationName(variationName); }else{ faqCF.setVariationName("master"); } } return faqCF; } catch (RepositoryException e) { LOG.error("Error collecting search results", e); return null; } }) .filter(Objects::nonNull) .collect(Collectors.toList()); } } catch (Exception e) { LOG.error("exception" , e); } }

 

 

This post is no longer active and is closed to new replies. Need help? Start a new post to ask your question.
Best answer by pulkitvashisth

This way you can mock the ResourceResolver, QueryBuilder, Query, and Session objects using

Mockito

// Mock objects
@Mock
private ResourceResolver resourceResolver;
@Mock
private QueryBuilder queryBuilder;
@Mock
private Query query;
@Mock
private Session session;
@Mock
private SearchResult searchResult;

// When-Then mocking
when(resourceResolver.adaptTo(QueryBuilder.class)).thenReturn(queryBuilder);
when(resourceResolver.adaptTo(Session.class)).thenReturn(session);
when(queryBuilder.createQuery(any(PredicateGroup.class), eq(session))).thenReturn(query);
when(query.getResult()).thenReturn(searchResult);

// Your test method here

In this code, @Mock creates mock objects, and when().thenReturn() specifies the output of the method calls on mocks1.

Please note that this is a basic example. You might need to add more mocking depending on your test cases. Also, remember to add @RunWith(MockitoJUnitRunner.class) at the class level to initialize these mocks1.

For more information about Mockito and unit testing in AEM, you can refer to these resources:

 

3 replies

Harwinder-singh
Community Advisor
Community Advisor
January 9, 2024

@sreenu539 Any specific reason why you want a real object instead of the mock objects provided by the testing API?

If you want to test the query performance, then you can simply get real production content synced to your local environment and look at the query performance using tools like Explain Query.

Based on the results , you can then further look at any optimization opportunities by considering aspects like creating an index, modify the query itself , evaluate whether or not ordering is important for your use case or not etc.

 

More details on how you can optimize your query performance : 

https://experienceleague.adobe.com/docs/experience-manager-cloud-service/content/operations/query-and-indexing-best-practices.html?lang=en

 

pulkitvashisth
Community Advisor
pulkitvashisthCommunity AdvisorAccepted solution
Community Advisor
January 9, 2024

This way you can mock the ResourceResolver, QueryBuilder, Query, and Session objects using

Mockito

// Mock objects
@Mock
private ResourceResolver resourceResolver;
@Mock
private QueryBuilder queryBuilder;
@Mock
private Query query;
@Mock
private Session session;
@Mock
private SearchResult searchResult;

// When-Then mocking
when(resourceResolver.adaptTo(QueryBuilder.class)).thenReturn(queryBuilder);
when(resourceResolver.adaptTo(Session.class)).thenReturn(session);
when(queryBuilder.createQuery(any(PredicateGroup.class), eq(session))).thenReturn(query);
when(query.getResult()).thenReturn(searchResult);

// Your test method here

In this code, @Mock creates mock objects, and when().thenReturn() specifies the output of the method calls on mocks1.

Please note that this is a basic example. You might need to add more mocking depending on your test cases. Also, remember to add @RunWith(MockitoJUnitRunner.class) at the class level to initialize these mocks1.

For more information about Mockito and unit testing in AEM, you can refer to these resources:

 
EstebanBustamante
Community Advisor and Adobe Champion
Community Advisor and Adobe Champion
January 9, 2024

I think the approach provided by @pulkitvashisth is the best way to test it, theoretically, you don't need to test the Search API that's why mocking all that processing is ok, what you can do further is to return your resources loaded from a JSON file, that way you have control over what things will be returned, see below as example:

 

 

Query mockQuery = mock(Query.class); SearchResult mockSearchResult = mock(SearchResult.class); when(mockQueryBuilder.createQuery(any(), any())).thenReturn(mockQuery); when(mockQuery.getResult()).thenReturn(mockSearchResult); //Mocking the first result from the query Hit result1 = mock(Hit.class); //This will allow you to load a resource previously loaded via context.load().json() when(result1.getResource()).thenReturn(context.currentResource("/content/myfolder/jcr:content")); List<Hit> mockedHits = new ArrayList<>(); mockedHits.add(result1); when(mockSearchResult.getHits()).thenReturn(mockedHits);

 

 

Hope this helps

Esteban Bustamante