C.2. Sample Pax-Exam Test Class

Sample test class

Example C.2, “FeaturesText Class” shows an example of how to write a test class for Apache Karaf in the Pax-Exam testing framework. The FeaturesText class configures the Apache Karaf environment, installs the obr and wrapper features, and then runs a test against the two features (where the obr and wrapper features implement particular sets of commands in the command console).

Example C.2. FeaturesText Class

// Java
/*
 * Licensed to the Apache Software Foundation (ASF)
 * ...
 */
package org.apache.karaf.shell.itests;

import org.apache.karaf.testing.AbstractIntegrationTest;
import org.apache.karaf.testing.Helper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.junit.Configuration;
import org.ops4j.pax.exam.junit.JUnit4TestRunner;
import org.osgi.service.blueprint.container.BlueprintContainer;
import org.osgi.service.command.CommandProcessor;
import org.osgi.service.command.CommandSession;

import static org.junit.Assert.assertNotNull;
import static org.ops4j.pax.exam.CoreOptions.felix;
import static org.ops4j.pax.exam.CoreOptions.maven;
import static org.ops4j.pax.exam.CoreOptions.systemProperty;
import static org.ops4j.pax.exam.CoreOptions.waitForFrameworkStartup;
import static org.ops4j.pax.exam.OptionUtils.combine;
import static org.ops4j.pax.exam.container.def.PaxRunnerOptions.scanFeatures;

import static org.ops4j.pax.exam.container.def.PaxRunnerOptions.workingDirectory;

@RunWith(JUnit4TestRunner.class) 1
public class FeaturesTest extends AbstractIntegrationTest { 2

    @Test 3
    public void testFeatures() throws Exception {
        // Make sure the command services are available
        assertNotNull(getOsgiService(BlueprintContainer.class, "osgi.blueprint.container.symbolicname=org.apache.karaf.shell.obr", 20000));
        assertNotNull(getOsgiService(BlueprintContainer.class, "osgi.blueprint.container.symbolicname=org.apache.karaf.shell.wrapper", 20000));
        // Run some commands to make sure they are installed properly
        CommandProcessor cp = getOsgiService(CommandProcessor.class); 4
        CommandSession cs = cp.createSession(System.in, System.out, System.err);
        cs.execute("obr:listUrl");
        cs.execute("wrapper:install --help");
        cs.close();
    }

    @Configuration 5
    public static Option[] configuration() throws Exception{
        return combine( 6
            // Default karaf environment
            Helper.getDefaultOptions( 7
                // this is how you set the default log level when using pax logging (logProfile)
                systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value("DEBUG")),

            // add two features
            scanFeatures( 8
                    maven().groupId("org.apache.karaf").artifactId("apache-felix-karaf").type("xml").classifier("features").versionAsInProject(),
                    "obr", "wrapper"
            ),

            workingDirectory("target/paxrunner/features/"), 9

            waitForFrameworkStartup(), 10
            
            // Test on the felix OSGi framework
            felix() 11
        );
    }

}
1
The @RunWith annotation instructs JUnit 4 to run the following test with the Pax-Exam test runner class, JUnit4TestRunner. This is the key step to integrate JUnit 4 with the Pax-Exam testing framework.
2
In order to integrate this JUnit test properly with Apache Karaf, you are required to derive this test class from org.apache.karaf.testing.AbstractIntegrationTest.
The AbstractIntegrationTest base class also provides some helper methods that access the bundle context: getOsgiService() methods, for obtaining a reference to an OSGi service, and the getInstalledBundle() method, for obtaining a reference to an org.osgi.framework.bundle object.
3
The @Test annotation is a standard JUnit 4 annotation that identifies the following method as a test method that is to be executed in the testing framework.
4
This line gives an example of how to use the getOsgiService() helper method to obtain an OSGi service from the OSGi container. In this example, the service is identified by specifying its Java type, org.osgi.service.command.CommandProcessor. The CommandProcessor service is the Apache Karaf service that has the capability to process console commands.
5
The @Configuration annotation is a Pax-Exam-specific annotation that marks the following the method as the configuration method that sets Pax-Exam testing options. The configuration method must be declared as public static and must have a return value of type, org.ops4j.pax.exam.Option[].
6
The OptionUtils.combine() method combines a given options array (of Option[] type) in the first argument with the options in the remaining arguments, returning an options array that contains all of the options.
7
The getDefaultOptions() method from the org.apache.karaf.testing.Helper class returns an options array containing all of the system property settings and option settings required to initialize Apache Karaf for the Pax-Exam testing framework.
If there are any Java system properties in the Apache Karaf environment that you would like to customize, you can pass the properties as optional arguments to the getDefaultOptions() method. In the example shown here, the system property for the Pax logging level is set to DEBUG.
8
The Pax-Exam framework supports the concept of Apache Karaf features (see Chapter 8, Deploying Features). You can use the PaxRunnerOptions.scanFeatures() method to install specific features in the OSGi container before the test is run.
The location of the relevant features repository is specified by passing a Pax URL as the first argument to scanFeatures(). In this example, the URL is constructed by creating a Pax Mvn URL (see Section A.3, “Mvn URL Handler”) with the fluent API from the CoreOptions class. Subsequent arguments specify which features to install—in this example, the obr and wrapper features.
9
The workingDirectory() option specifies the directory where the Pax Runner provisioning module looks for OSGi bundles.
10
The waitForFrameworkStartup() specifies that the testing framework should wait for a default length of time (five minutes) for the OSGi framework to start up before timing out. To specify the timeout explicitly, you could use the waitForFrameworkStartupFor(long millis) method instead, where the timeout is specified in milliseconds.
11
The felix() option is used to specify that the test should be run in the Felix OSGI framework.