Mock implementation of selected OSGi APIs for easier testing.
For JUnit 5:
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.testing.osgi-mock.junit5</artifactId>
</dependency>
For JUnit 4:
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.testing.osgi-mock.junit4</artifactId>
</dependency>
See latest version on the downloads page.
There are two major version ranges available:
The mock implementation supports:
Bundle, BundleContext and ComponentContext objects and navigate between them./OSGI-INF/<pid>.xml and from /OSGI-INF/serviceComponents.xmlLogService which logs to SLF4J in JUnit contextEventAdmin which supports EventHandler servicesConfigAdminSince osgi-mock 2.0.0:
The OsgiContext object provides access to mock implementations of:
Additionally it supports:
The OSGi mock context can be injected into a JUnit test using a custom JUnit extension named OsgiContextExtension. This extension takes care of all initialization and cleanup tasks required to make sure all unit tests can run independently (and in parallel, if required).
Example:
@ExtendWith(OsgiContextExtension.class)
public class ExampleTest {
private final OsgiContext context = new OsgiContext();
@Test
public void testSomething() {
// register and activate service with configuration
MyService service1 = context.registerInjectActivateService(new MyService(),
"prop1", "value1");
// get service instance
OtherService service2 = context.getService(OtherService.class);
}
}
It is possible to combine such a unit test with a @ExtendWith annotation e.g. for Mockito JUnit Jupiter Extension.
The OSGi mock context can be injected into a JUnit test using a custom JUnit rule named OsgiContext. This rule takes care of all initialization and cleanup tasks required to make sure all unit tests can run independently (and in parallel, if required).
Example:
public class ExampleTest {
@Rule
public final OsgiContext context = new OsgiContext();
@Test
public void testSomething() {
// register and activate service with configuration
MyService service1 = context.registerInjectActivateService(new MyService(),
"prop1", "value1");
// get service instance
OtherService service2 = context.getService(OtherService.class);
}
}
It is possible to combine such a unit test with a @RunWith annotation e.g. for Mockito JUnit Runner.
The factory class MockOsgi allows to instantiate the different mock implementations.
Example:
// get bundle context
BundleContext bundleContext = MockOsgi.newBundleContext();
// get component context with configuration
BundleContext bundleContext = MockOsgi.newComponentContext(properties,
"prop1", "value1");
It is possible to simulate registering of OSGi services (backed by a simple hash map internally):
// register service
bundleContext.registerService(MyClass.class, myService, properties);
// get service instance
ServiceReference ref = bundleContext.getServiceReference(MyClass.class.getName());
MyClass service = bundleContext.getService(ref);
It is possible to simulate OSGi service activation, deactivation and dependency injection and the mock implementation tries to to its best to execute all as expected for an OSGi environment.
Example:
// get bundle context
BundleContext bundleContext = MockOsgi.newBundleContext();
// create service instance manually
MyService service = new MyService();
// inject dependencies
MockOsgi.injectServices(service, bundleContext);
// activate service
MockOsgi.activate(service, props);
// operate with service...
// deactivate service
MockOsgi.deactivate(service);
Please note:
/OSGI-INF. They are generated automatically by the Maven SCR plugin, but might be missing if your clean and build the project within your IDE (e.g. Eclipse). In this case you have to compile the project again with maven and can run the tests - or use a Maven IDE Integration like m2eclipse.If you want to provide your own configuration to an OSGi service that you do not register and activate itself in the mock context you can provide your own custom OSGi configuration via the mock implementation of the ConfigAdmin service.
Example:
ConfigurationAdmin configAdmin = context.getService(ConfigurationAdmin.class);
Configuration myServiceConfig = configAdmin.getConfiguration(MY_SERVICE_PID);
Dictionary<String, Object> props = new Hashtable<String, Object>();
props.put("prop1", "value1");
myServiceConfig.update(props);
OSGi Mocks supports "Context Plugins" that hook into the lifecycle of each test run and can prepare test setup before or after the other setUp actions, and execute test tear down code before or after the other tearDown action.
To define a plugin implement the org.apache.sling.testing.mock.osgi.context.ContextPlugin<OsgiContextImpl> interface. For convenience it is recommended to extend the abstract class org.apache.sling.testing.mock.osgi.context.AbstractContextPlugin<OsgiContextImpl>. These plugins can be used with OSGi Mock context, but also with context instances deriving from it like Sling Mocks and AEM Mocks. In most cases you would just override the afterSetUp method. In this method you can register additional OSGi services or do other preparation work. It is recommended to define a constant pointing to a singleton of a plugin instance for using it.
To use a plugin in your unit test class, use the OsgiContextBuilder class instead of directly instantiating the OsgiContextclass. This allows you in a fluent style to configure more options, with the plugin(...) method you can add one or more plugins.
Example:
OsgiContext context = new OsgiContextBuilder().plugin(MY_PLUGIN).build();
More examples: