Hi,
I followed this AEM tutorial https://experienceleague.adobe.com/docs/experience-manager-learn/cloud-service/developing/advanced/s...
to set up a service class that loads once service user object is available.
@Component(
reference = {
@Reference(
name = wknd-examples-statistics,
service = ServiceUserMapped.class,
target = "(subServiceName=wknd-examples-statistics)"
)
}
)
public class ContentStatisticsImpl implements ContentStatistics {
My service works fine. The issue is when I am unit testing.
I get this error while unit testing:
org.apache.sling.testing.mock.osgi.ReferenceViolationException: Unable to inject mandatory reference 'wknd-examples-statistics' (org.apache.sling.serviceusermapping.ServiceUserMapped) for class com.adobe.aem.wknd.examples.core.statistics.impl.ContentStatisticsImpl
: no matching services were found. bundleContext=org.apache.sling.testing.mock.osgi.MockBundleContext@298f7b0a.
Error occurs when I inject the service as below:
context.registerInjectActivateService(newContentStatisticsImpl());
How do i mock @reference. Please help
Solved! Go to Solution.
Views
Replies
Total Likes
Hi, I resolved it by adding a bind method:
@Component(
reference = {
@Reference(
name = wknd-examples-statistics,
service = ServiceUserMapped.class,
target = "(subServiceName=wknd-examples-statistics)",
bind = "setServiceUserMapped"
)
}
)
public class ContentStatisticsImpl implements ContentStatistics {
@Reference
private ServiceUserMapped serviceUserMapped;
public void setServiceUserMapped(ServiceUserMapped serviceUserMapped) {
this.serviceUserMapped = serviceUserMapped;
}
//other code
}
Test case:
public class ContentStatisticsImplTest {
@BeforeEach
public void setup() {
serviceUserMapped = mock(ServiceUserMapped.class);
context.registerService(ServiceUserMapped.class,serviceUserMapped, ImmutableMap.of(ServiceUserMapped.SUBSERVICENAME,"wknd-examples-statistics"));
}
Thanks for your help. @sherinregi
Hi @sindhusr
One thing i notice here is you are trying yo use registerInjectActivateService on the same class you are on. In your case you are referencing a markerservice serviceusermapped and that reference needs to be mocked inorder to prevent this exception .
Can you try to do inject that and use the same in setup and then invoke
Try something similar
Thanks,
Sherin
Hi @sherinregi , Thank you for your response.
What is ServiceUserMapped.clreplaced? I cannot resolve that on my IDE nor can I find references to it.
This is what I tried:
ServiceUserMapped serviceUserMapped = Mockito.mock(ServiceUserMapped.class);
context.registerService(ServiceUserMapped.class,serviceUserMapped,ImmutableMap.of(ServiceUserMapped.SUBSERVICENAME,"wknd-examples-statistics"));
context.registerInjectActivateService(newContentStatisticsImpl());
Now I get the below error:
java.lang.RuntimeException: No bind/unbind method name or file name defined for reference wknd-examples-statistics
Hi @sindhusr
You can ignore the clreplaced one. The steps you followed looks rite to me . The error now you are getting looks a different one and i feel it could be related to the details given in the below links. Could you please check on that
https://groups.google.com/g/wcm-io-dev/c/JzFnXsY6XZk?pli=1
They have explained a sequence of steps to follow. Also check the import packages for mock
Hi, I resolved it by adding a bind method:
@Component(
reference = {
@Reference(
name = wknd-examples-statistics,
service = ServiceUserMapped.class,
target = "(subServiceName=wknd-examples-statistics)",
bind = "setServiceUserMapped"
)
}
)
public class ContentStatisticsImpl implements ContentStatistics {
@Reference
private ServiceUserMapped serviceUserMapped;
public void setServiceUserMapped(ServiceUserMapped serviceUserMapped) {
this.serviceUserMapped = serviceUserMapped;
}
//other code
}
Test case:
public class ContentStatisticsImplTest {
@BeforeEach
public void setup() {
serviceUserMapped = mock(ServiceUserMapped.class);
context.registerService(ServiceUserMapped.class,serviceUserMapped, ImmutableMap.of(ServiceUserMapped.SUBSERVICENAME,"wknd-examples-statistics"));
}
Thanks for your help. @sherinregi
Hi @sindhusr : You can refer this as well- https://experienceleaguecommunities.adobe.com/t5/adobe-experience-manager/aem-servlet-junit-writing-...
Hi @sindhusr
when unit testing OSGi components that have@Reference annotations, you need to simulate the OSGi environment and register the services your component depends on. The error you're encountering indicates that the required service (wknd-examples-statistics) is not being provided in the test environment.
You can use the @Designate annotation along with @OsgiService to mock and register the required service during unit testing. Here's an example:
import org.apache.sling.serviceusermapping.ServiceUserMapped;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
@Component(
immediate = true,
service = ContentStatistics.class
)
@Designate(ocd = ContentStatisticsImpl.Config.class)
public class ContentStatisticsImpl implements ContentStatistics {
@Reference
private ServiceUserMapped wkndExamplesStatisticsService;
// Other code...
@Activate
@Modified
protected void activate(Config config) {
// Your activation logic
}
// Configuration interface
@ObjectClassDefinition(name = "Content Statistics Configuration")
public @interface Config {
@AttributeDefinition(name = "Sub Service Name", description = "The sub-service name")
String subServiceName() default "wknd-examples-statistics";
}
}
you can then use @OsgiServiceto mock and register the required service:
import org.apache.sling.serviceusermapping.ServiceUserMapped;
import org.junit.jupiter.api.Test;
import org.apache.sling.testing.mock.osgi.MockOsgi;
class ContentStatisticsImplTest {
@Test
void testContentStatistics() {
// Mock the ServiceUserMapped service
ServiceUserMapped wkndExamplesStatisticsService = MockOsgi
.newService(ServiceUserMapped.class)
.property("subServiceName", "wknd-examples-statistics")
.build();
// Register the mocked service
MockOsgi.injectServices(new ContentStatisticsImpl(), wkndExamplesStatisticsService);
// Your test logic here
}
}
This approach allows you to simulate the OSGi environment and register the required services for your unit tests.
Thanks.