Expand my Community achievements bar.

SOLVED

Unit Test for a service using JobManger api

Avatar

Level 2

Hi Everybody. 

I opened a previous ticket : https://experienceleaguecommunities.adobe.com/t5/adobe-experience-manager/mocking-jobmanager-in-juni... because i had issue on mocking annotations. 

 

I am opening a new ticket ( related to the previous ) because i will appreciate help or explanations that let me understand the process.

 

I have a service : scheduleJob. 

In that service i have a function scheduling a job. It will looks like :

class ScheduleJob...
public void
startMyJob(String topic, Map<String, Object> jobProperties) {

JobBuilder jobBuilder =jobManager.createJob(topic);
jobBuilder.properties(jobProperties); Line XXX
JobBuilder.ScheduleBuilder scheduleBuilder =jobBuilder.schedule();
scheduleBuilder.cron(schedulerExpression);
List<String> errors = new ArrayList<>();
ScheduledJobInfo scheduledJobInfo=scheduleBuilder.add(errors);
if(scheduledJobInfo==null){
do Something
}
}
else{
do something else
}

}

and in my unit test i have something like that : 

 

class scheduleJobTest {

@Mock
private JobManager jobManager;

@Mock
private JobBuilder jobBuilder;

@Mock
private JobBuilder.ScheduleBuilder scheduleBuilder;

@InjectMocks
private ScheduleJob scheduleJob = new ScheduleJob() ;


AemContext aemContext = new AemContext();


@BeforeEach
void setUp() {
aemContext.registerService(JobManager.class,jobManager);
aemContext.registerService(JobBuilder.class,jobBuilder);
aemContext.registerService(JobBuilder.ScheduleBuilder.class,scheduleBuilder);
aemContext.registerInjectActivateService(ScheduleJob);
}

@Test
startMyJob(){
scheduleJob.startMyJob(); Line XXY
assert...

}

And it gives me a null pointer exception at line XXY inside the function scheduleJob.startMyJob at Line XXX.

 

Maybe i am not understanding how it works and i am not using the right method to do it. But the idea is :

I mock the JobManager, JobBuilder and all the ref/services needed in my scheduleJob Class and then i can just call my function and test it in UnitTestClass. Or do i need to stub them ? If i do that, where is the point to call my function ?

 

 

If someone could help me it will be really nice

 

Thanks in advance,

Regards

 

1 Accepted Solution

Avatar

Correct answer by
Level 4

Hi @Dody ,

Since you are mocking JobManager and not actually initializing it, you will not get actual working on the service and hence every operation that you do with JobManager has to be handled by you in test class accordingly.

 

Refer this example:

@Mock

private ResourceResolver resolver;

 

@Mock

private ResourceResolverFactory factory;

 

@InjectMocks

private MyService myService;

 

now if someMethod() in myService is calling factory.getServiceResourceResolver() method you have to tell your test method want has to be returned from this call.

This can be done as shown below:

lenient().when(factory.getServiceResourceResolver(anyMap())).thenReturn(resolver);

 

Please be noted that you can return a mocking object or any value of your choice. In my case I am returning a mock resourceResolver.

 

In your case it should be, add below line before Line XXY

lenient().when(jobManager.createJob(any()).thenReturn(jobBuilder); (same applies for jobBuilder again)

 

Refer to this link https://experienceleague.adobe.com/docs/experience-manager-learn/getting-started-wknd-tutorial-devel... 

 

Thanks!

 

View solution in original post

4 Replies

Avatar

Correct answer by
Level 4

Hi @Dody ,

Since you are mocking JobManager and not actually initializing it, you will not get actual working on the service and hence every operation that you do with JobManager has to be handled by you in test class accordingly.

 

Refer this example:

@Mock

private ResourceResolver resolver;

 

@Mock

private ResourceResolverFactory factory;

 

@InjectMocks

private MyService myService;

 

now if someMethod() in myService is calling factory.getServiceResourceResolver() method you have to tell your test method want has to be returned from this call.

This can be done as shown below:

lenient().when(factory.getServiceResourceResolver(anyMap())).thenReturn(resolver);

 

Please be noted that you can return a mocking object or any value of your choice. In my case I am returning a mock resourceResolver.

 

In your case it should be, add below line before Line XXY

lenient().when(jobManager.createJob(any()).thenReturn(jobBuilder); (same applies for jobBuilder again)

 

Refer to this link https://experienceleague.adobe.com/docs/experience-manager-learn/getting-started-wknd-tutorial-devel... 

 

Thanks!

 

Avatar

Level 2

Hello @MohitKumarK ,

 

Thanks for the answer. It's more clear now.

 

I did that and then the tests passes.

 

So if i understood well, in my test method i am only calling my serviceMethod. 

@Test
startMyJob(){
scheduleJob.startMyJob();

 Then if i correctly set up the right "when..thenReturn" instructions, i had nothing to do more ? No need to assertTrue.../equals.. nothing ?

 

Thanks in advance

Regards

Avatar

Level 4

Hi @Dody ,

You still need to do assertions based on your class that you intended to test. That is the main purpose of writing a test case. In your case you are writing a junit class for a service so you can assert outcome of methods inside it.

 

Please mark correct answer such that wider people can refer this question.

Thanks!

Avatar

Level 2

Hi @MohitKumarK ,

 

But here is my question, because my service method is only creating a scheduled job and nothing is returned. 

So i mocked everything, it's fine but i don't now what to assert.

 

Thanks for your help. I put it as correct answer.