How to unit test OSGi service with ReferencePolicy=DYNAMIC using AEMContext | Community
Skip to main content
Level 2
February 16, 2024
Question

How to unit test OSGi service with ReferencePolicy=DYNAMIC using AEMContext

  • February 16, 2024
  • 3 replies
  • 2597 views

Hi,

   I have an OSGi service (MyService) that is referencing a list of OSGi services implementing the same interface (SecondService). Debugging this code with AEM 6.5.17.0 is properly injecting all the OSGi services (serviceList has multiple objects), but when I try to replicate that in my unit test using AEMContext.registerService() to inject multiple OSGi services, I see that the reference variable is not getting injected properly. What am I doing wrong? 
Here is a sample code for the MyService where the serviceList is getting injected properly on my local AEM instance.

 

package com.mypackage; import org.osgi.service.component.annotations.*; import java.util.*; @Component(service = MyService.class,immediate = true) public class MyServiceImpl implements MyService { @3214626(service = SecondService.class, cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC, bind = "bindMethod", unbind = "unbindMethod") private volatile List<SecondService> serviceList; protected void bindMethod(){ //DO SOMETHING } protected void unbindMethod(){ //DO SOMETHING } }

 

And the sample code for the unit tests that doesn't inject serviceList properly. 

 

package com.mypackage; import io.wcm.testing.mock.aem.junit.AemContext; import org.apache.sling.testing.mock.sling.ResourceResolverType; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) public class MyServiceTest { @Rule public final AemContext context = new AemContext(ResourceResolverType.RESOURCERESOLVER_MOCK); @Mock SecondService s1; @Mock SecondService s2; @2785667 public void sampleTest(){ context.registerService(SecondService.class, s1); context.registerService(SecondService.class, s2); MyService service = context.registerInjectActivateService(new MyServiceImpl()); } }

 

In both cases (local debug and unit test), I am debugging the MyService.bindMethod() to check whether the serviceList is injected or not. 

Regards,
Raj

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

3 replies

Raja_Reddy
Community Advisor
Community Advisor
February 16, 2024

Hi @rajdevms 

You are missing the updated method in your MyServiceImpl class. The updated method is called by the OSGi container when the service is updated. In your case, when you register the services in the unit test, the updated method is not called, and hence the serviceList is not getting updated.

Please check this changes

 

package com.mypackage; import org.osgi.service.component.annotations.*; import java.util.*; @Component(service = MyService.class,immediate = true) public class MyServiceImpl implements MyService { @reference(service = SecondService.class, cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC, bind = "bindMethod", unbind = "unbindMethod") private volatile List<SecondService> serviceList; protected void bindMethod(){ //DO SOMETHING } protected void unbindMethod(){ //DO SOMETHING } @Activate protected void activate() { //DO SOMETHING } @Deactivate protected void deactivate() { //DO SOMETHING } @Modified protected void updated() { //DO SOMETHING } }

 

 

rajdevmsAuthor
Level 2
February 16, 2024

Hi @raja_reddy ,
    Thank you for your response. Can you help me understand why adding the updated() method would solve the problem? 
    The code that I shared before works as expected in AEM run-time but does not when running the unit test. So, the solution for this problem would involve changing the unit test and not the actual OSGi service. 

Regards,

Raj

rajdevmsAuthor
Level 2
February 20, 2024

Hi @rajdevms 

Adding the `updated()` method to your OSGi service implementation would not solve the problem with your unit test. The `updated()` method is called by the OSGi framework when the configuration of the service is updated. It is used to handle any changes to the configuration properties of the service.

If your code works as expected in AEM run-time but not in the unit test, it is possible that the unit test environment is not properly configured or that there are differences in the environment that are causing the issue. You may need to modify your unit test to properly simulate the AEM run-time environment.


that is exactly what I looking for. How do I fix this `it is possible that the unit test environment is not properly configured or that there are differences in the environment that are causing the issue. You may need to modify your unit test to properly simulate the AEM run-time environment.`

kautuk_sahni
Community Manager
Community Manager
February 21, 2024

@rajdevms Did you find the suggestions from users helpful? Please let us know if more information is required. Otherwise, please mark the answer as correct for posterity. If you have found out solution yourself, please share it with the community.

Kautuk Sahni
rajdevmsAuthor
Level 2
February 21, 2024

Hi @kautuk_sahni, I have only received a single response and that hasn't solved my problem. This post should stay active. 

July 1, 2024

What worked for me was a different signature of the method registerService

context.registerService(class, instance, props)

if to go with your example

context.registerService(SecondService.class, s1, new HashMap<>());