Pax Exam + Karaf容器注入Custom Service遇到ClassNotFoundException

时间:2013-11-30 14:48:57

标签: java pax-exam integration-testing

最近我写了一个使用Pax考试在Karaf容器中运行的集成测试,这是我的代码:

package com.mercury.mof.integration.tests;

import static org.ops4j.pax.exam.CoreOptions.maven;
import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
import static org.ops4j.pax.exam.CoreOptions.provision;
import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.features;
import static org.ops4j.pax.tinybundles.core.TinyBundles.bundle;

import java.util.HashSet;
import java.util.Set;

import javax.inject.Inject;

import org.apache.karaf.features.Feature;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.OptionUtils;
import org.ops4j.pax.exam.ProbeBuilder;
import org.ops4j.pax.exam.TestProbeBuilder;
import org.ops4j.pax.exam.junit.PaxExam;
import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
import org.ops4j.pax.exam.spi.reactors.PerMethod;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;

import com.mercury.mof.dataplatform.api.impl.DefaultMofDataPlatformModule;
import com.mercury.mof.foundation.framework.api.modular.IFramework;
import com.mercury.mof.foundation.framework.api.modular.IModule;

@RunWith(PaxExam.class)
@ExamReactorStrategy(PerMethod.class)
public class FeaturesTest extends KarafTestSupport {

    @ProbeBuilder
    public TestProbeBuilder probeConfiguration(TestProbeBuilder probe) {
        probe.setHeader(
            Constants.DYNAMICIMPORT_PACKAGE,
                "*,org.apache.felix.service.*;status=provisional");
    return probe;
}


//This is my custom service ,and when running tests Pax Exam always report     ClassNotFoundException. 
    @Inject
    IFramework framework;

@Override
@Configuration
public Option[] config() {
    Option[] option = super.config();

    // KarafFeatureDependencyGenerator generator = new
    // KarafFeatureDependencyGenerator();
    // System.out.println(maven().groupId(
    // "org.apache.karaf.assemblies.features")
    // .artifactId("standard").type("xml")
    // .classifier("features")
    // .versionAsInProject().getURL());
    //
    //
    // try{
    // System.out.println(
    // generator.analysisFeature(System.getenv("m2_repo"), maven().groupId(
    // "org.apache.karaf.assemblies.features")
    // .artifactId("enterprise").type("xml")
    // .classifier("features")
    // .versionAsInProject().getURL()));
    // }catch(Exception e){
    // e.printStackTrace();
    // }

    Option[] combined = OptionUtils
            .combine(
                    option,

                    features(
                            maven().groupId(
                                    "org.apache.karaf.assemblies.features")
                                    .artifactId("standard").type("xml")
                                    .classifier("features")
                                    .versionAsInProject(), "http",
                            "http-whiteboard"),
                    features(
                            maven().groupId(
                                    "org.apache.karaf.assemblies.features")
                                    .artifactId("enterprise").type("xml")
                                    .classifier("features")
                                    .versionAsInProject(), "transaction",
                            "jpa", "jndi"),

                    mavenBundle("org.osgi", "org.osgi.compendium", "4.2.0"),
                    mavenBundle("org.osgi", "org.osgi.core", "4.2.0"),
                    mavenBundle("org.osgi", "org.osgi.enterprise", "4.2.0"),
                    mavenBundle("com.mercury", "mof-foundation-commons",
                            "1.0.0.alpha"),
                    mavenBundle("com.mercury.mof",
                            "mof-foundation-framework-impl", "1.0.0.alpha"),
                    mavenBundle("com.mercury.mof",
                            "mof-foundation-cache-api", "1.0.0.alpha"),
                    mavenBundle("com.mercury.mof", "mof-data-platform-api",
                            "1.0.0.alpha"),
                    mavenBundle("com.mercury.mof",
                            "mof-data-platform-impl", "1.0.0.alpha"),
                    mavenBundle("com.mercury.mof",
                            "mof-foundation-framework-api", "1.0.0.alpha"),
                    mavenBundle("com.mercury.mof",
                            "mof-foundation-security-api", "1.0.0.alpha"),
                    mavenBundle("com.mercury.mof",
                            "mof-foundation-cache-api,1.0.0.alpha"),
                    mavenBundle("com.mercury.mof",
                            "mof-foundation-rbac-api", "1.0.0.alpha"),

                    provision(bundle()
                            .set("Import-Package",
                                    "org.osgi.service.blueprint;version=\"[1.0.0,2.0.0)\",com.mercury.mof.foundation.framework.api.modular;version=\"[1.0,2)\",com.mercury.mof.dataplatform.api;version=\"[1.0,2)\",com.mercury.mof.foundation.commons.inf.lifecycle;version=\"[1.0,2)\",com.mercury.mof.foundation.framework.api.impl.modular;version=\"[1.0,2)\"")


                            .set("Export-Package",
                                    "com.mercury.mof.dataplatform.api.impl;uses:=\"com.mercury .mof.foundation.framework.api.impl.modular,com.mercury.mof.foundation.c ommons.inf.lifecycle\";version=\"1.0.0.alpha\"")
                            .set("DynamicImport-Package", "*")
                            .set(Constants.BUNDLE_MANIFESTVERSION, "2")
                            .set(Constants.BUNDLE_SYMBOLICNAME,
                                    "com.mercury.mof.mof-data-platform-impl-integration-test")
                            .set(Constants.BUNDLE_VERSION, "1.0.0.alpha")
                            .add(IFramework.class)
                            .add("OSGI-INF/blueprint/blueprint.xml",
                                    getClass()
                                            .getResource(
                                                    "/OSGI-INF/blueprint/blueprint.xml"))

                            .build())

            );

    return combined;
}

@Test
public void testTransactionFeature() throws Exception {
    Assert.assertNotNull(this.featuresService);
    assertFeatureInstalled("http");
    assertFeatureInstalled("jpa");
    assertFeatureInstalled("jndi");
    assertFeatureInstalled("transaction");


    Assert.assertNotNull(this.blueprintContainer);

    Assert.assertNotNull(this.blueprintContainer.getComponentInstance("mofFrameworkServiceImpl"));
    // Assert.assertNotNull(module);

}

protected Set<Feature> getFeatures(String features) throws Exception {
    String[] featureArray = features.split("\\s");
    Set<Feature> featureSet = new HashSet<Feature>();
    for (String s : featureArray) {

        if (s == null || (s = s.trim()).isEmpty()) {
            continue;
        }
        Feature feature = this.featuresService.getFeature(s);
        if (feature == null) {
            throw new IllegalArgumentException("The feature which named:"
                    + s + " can not be found.");
        }
        featureSet.add(feature);
    }
    return featureSet;
}

}

但我发现它无法通过测试,因为测试包无法找到我的自定义服务类(IFramework框架)并报告:

java.lang.ClassNotFoundException:     com.mercury.mof.foundation.framework.api.modular.IFramework not found by PAXEXAM-PROBE-45604164-c35f-448b-9627-af8adb7e16f7 [110]
    at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1460)
    at org.apache.felix.framework.BundleWiringImpl.access$400(BundleWiringImpl.java:72)
    at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1843)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
    at java.lang.Class.getDeclaredFields0(Native Method)
    at java.lang.Class.privateGetDeclaredFields(Class.java:2317)
    at java.lang.Class.getDeclaredFields(Class.java:1762)
    at org.junit.runners.model.TestClass.<init>(TestClass.java:49)
    at org.junit.runners.ParentRunner.<init>(ParentRunner.java:75)
    at org.junit.runners.BlockJUnit4ClassRunner.<init>(BlockJUnit4ClassRunner.java:57)
    at org.ops4j.pax.exam.invoker.junit.internal.ContainerTestRunner.<init>(ContainerTestRunner.java:53)
    at org.ops4j.pax.exam.invoker.junit.internal.ContainerTestRunnerBuilder.runnerForClass(ContainerTestRunnerBuilder.java:50)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
    at org.ops4j.pax.exam.invoker.junit.internal.ContainerTestRunnerClassRequest.getRunner(ContainerTestRunnerClassRequest.java:61)
    at org.junit.internal.requests.FilterRequest.getRunner(FilterRequest.java:31)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:138)
    at org.ops4j.pax.exam.invoker.junit.internal.JUnitProbeInvoker.invokeViaJUnit(JUnitProbeInvoker.java:123)
    at org.ops4j.pax.exam.invoker.junit.internal.JUnitProbeInvoker.findAndInvoke(JUnitProbeInvoker.java:96)
    at org.ops4j.pax.exam.invoker.junit.internal.JUnitProbeInvoker.call(JUnitProbeInvoker.java:72)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.ops4j.pax.exam.rbc.internal.RemoteBundleContextImpl.remoteCall(RemoteBundleContextImpl.java:80)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:322)
    at sun.rmi.transport.Transport$1.run(Transport.java:177)
    at sun.rmi.transport.Transport$1.run(Transport.java:174)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:173)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:553)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:808)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:667)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:722)

我不知道问题出在哪里,实际上我在我的基础测试中注入了一些标准的osgi服务,它就像一个魅力,为什么当我使用自己的服务时它会导致麻烦?任何人都可以给我一些提示吗?非常感谢

1 个答案:

答案 0 :(得分:1)

确保测试可以看到IFramework类的最佳方法是确保提供类的bundle安装在容器中。在@Configuration注释方法中使用mavenBundle是一个很好的方法。

您需要注意的事项: i)包含IFramework的包导出该类。 ii)如果您正在使用maven协调,请确保安装了人工制品(参见[1])。 iii)确保满足捆绑导出IFramework的依赖关系。

所以与您的代码相关的评论: i)您不需要安装osgi core,compendium&amp;企业(由karaf提供)。 ii)没有必要使用提供的东西来添加类和资源(我看到正在安装的类作为捆绑包和测试资源,无论如何都将可用。)

[1]:如果您的集成测试是与您在测试中使用的类相同的maven模块的一部分,则需要注意测试是在您的存储库中安装了artefact之前运行的,因此使用maven coords会导致问题。如果是这种情况,请考虑拆分测试,或不使用maven coords。