Expand my Community achievements bar.

SOLVED

Unit testing QueryBuilder and Query

Avatar

Level 5

What is the proper way to unit test QueryBuilder and Query?  Can I feed in mock data to the AemContext and have QueryBuilder execute against it?

 

Are there any examples or best practices that can be followed?

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

Do you have the unit test class with these annotations? 

 

@ExtendWith({ AemContextExtension.class, MockitoExtension.class })
@MockitoSettings(strictness = Strictness.LENIENT)
class UnitTest {
}

The same code works for me. 

View solution in original post

3 Replies

Avatar

Community Advisor

Some sample code to start with

 

 

    public static final String BASE_PAGE_PATH = "/content/we.retail/en";
    AemContext aemContext = new AemContext(ResourceResolverType.JCR_MOCK);

    @Mock
    private QueryBuilder queryBuilder;

    @Mock
    private Query query;

    @Mock
    private SearchResult searchResult;


@BeforeEach
    void setUp() throws Exception{
        aemContext.registerService(QueryBuilder.class, queryBuilder);
        aemContext.load().json("/page.json", BASE_PAGE_PATH);
        configureQueryBuilder();

    }

public void configureQueryBuilder() throws Exception {

        final List<Resource> results = new ArrayList<>();
        Resource pageResult1 = mock(Resource.class);
        Resource pageResult2 = mock(Resource.class);
        pageResult1 = aemContext.resourceResolver().getResource(BASE_PAGE_PATH+"/page1");
        pageResult2 = aemContext.resourceResolver().getResource(BASE_PAGE_PATH+"/page1");
        results.add(pageResult1);
        results.add(pageResult2);
        // More Generic mock of querybuilder calls
        lenient().when(queryBuilder.createQuery(any(PredicateGroup.class), any(Session.class))).thenReturn(query);
        lenient().when(query.getResult()).thenReturn(searchResult);
        lenient().when(searchResult.getResources()).thenReturn(results.iterator());
    }

 

  

So I've tried this, but this line of code returns null within my service:

 

Query query = queryBuilder.createQuery(PredicateGroup.create(paramMap), resolver.adaptTo(Session.class));

 

After this runs under the unit test, query is null- so future calls like query.setStart() throw a null reference exception.
 
In my configureQueryBuilder, I have it looking like this:
 
    public void configureQueryBuilder() throws Exception {
        final List<Resource> results = new ArrayList<>();
        Resource pageResult1 = mock(Resource.class);
        Resource pageResult2 = mock(Resource.class);
        pageResult1 = aemContext.resourceResolver().getResource(BASE_PAGE_PATH+"/page-1");
        pageResult2 = aemContext.resourceResolver().getResource(BASE_PAGE_PATH+"/page-2");

        results.add(pageResult1);
        results.add(pageResult2);

        doNothing().when(query).setStart(isA(long.class));

        lenient().when(query.getResult()).thenReturn(searchResult);

        // More Generic mock of querybuilder calls
        lenient().when(queryBuilder.createQuery(any(PredicateGroup.class), any(Session.class))).thenReturn(query);
        lenient().when(searchResult.getResources()).thenReturn(results.iterator());
    }
 
how do I get the Mock query object to return?  Maybe the mock is returning, but the Mock is null?

Avatar

Correct answer by
Community Advisor

Do you have the unit test class with these annotations? 

 

@ExtendWith({ AemContextExtension.class, MockitoExtension.class })
@MockitoSettings(strictness = Strictness.LENIENT)
class UnitTest {
}

The same code works for me.