2

我构建了一个非常简单的包,它具有零依赖项并且不导入任何包。它的唯一内容是一个 CalculatorService 接口和相应的实现类,其中只包含一个简单的 add(int a, int b) 方法。

我为这个包创建了两个 PaxExam 测试容器,一个使用 Karaf 容器,另一个使用 OSGI 容器。Karaf 容器测试工作正常,但 OSGI 测试容器不能。

澄清一点......如果我将 CalculatorService 注入到 OSGI 测试容器中,并在我的 JUnit 测试用例中直接实例化 CalculatorServiceImpl 类,它工作正常。所以我的简单包中的类对 OSGI 测试容器是可见的。

一些问题:

  • 我的 pom.xml 文件中是否缺少一些东西来完成这项工作?
  • 我应该向我的 OsgiTestClient.config() 方法添加更多包吗?
  • 关于保留什么的其他想法是从工作中剥离出来的例子?

以下是我在尝试将 CalculatorService 注入我的 PaxExam OSGI 测试容器时得到的堆栈跟踪。

org.ops4j.pax.swissbox.tracker.ServiceLookupException: gave up waiting for service info.xyz.common.Calculator
    at org.ops4j.pax.swissbox.tracker.ServiceLookup.getService(ServiceLookup.java:199)
    at org.ops4j.pax.swissbox.tracker.ServiceLookup.getService(ServiceLookup.java:136)
    at org.ops4j.pax.exam.inject.internal.ServiceInjector.injectField(ServiceInjector.java:89)
    at org.ops4j.pax.exam.inject.internal.ServiceInjector.injectDeclaredFields(ServiceInjector.java:69)
    at org.ops4j.pax.exam.inject.internal.ServiceInjector.injectFields(ServiceInjector.java:61)
    at org.ops4j.pax.exam.invoker.junit.internal.ContainerTestRunner.createTest(ContainerTestRunner.java:61)
    at org.junit.runners.BlockJUnit4ClassRunner$1.runReflectiveCall(BlockJUnit4ClassRunner.java:266)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:263)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.ops4j.pax.exam.invoker.junit.internal.ContainerTestRunner.runChild(ContainerTestRunner.java:68)
    at org.ops4j.pax.exam.invoker.junit.internal.ContainerTestRunner.runChild(ContainerTestRunner.java:37)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
    at org.ops4j.pax.exam.invoker.junit.internal.JUnitProbeInvoker.invokeViaJUnit(JUnitProbeInvoker.java:124)
    at org.ops4j.pax.exam.invoker.junit.internal.JUnitProbeInvoker.findAndInvoke(JUnitProbeInvoker.java:97)
    at org.ops4j.pax.exam.invoker.junit.internal.JUnitProbeInvoker.call(JUnitProbeInvoker.java:73)
    at org.ops4j.pax.exam.nat.internal.NativeTestContainer.call(NativeTestContainer.java:112)
    at org.ops4j.pax.exam.spi.reactors.AllConfinedStagedReactor.invoke(AllConfinedStagedReactor.java:84)
    at org.ops4j.pax.exam.junit.impl.ProbeRunner$2.evaluate(ProbeRunner.java:267)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.ops4j.pax.exam.junit.impl.ProbeRunner.run(ProbeRunner.java:98)
    at org.ops4j.pax.exam.junit.PaxExam.run(PaxExam.java:93)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

我的包含计算器服务的简单包的 pom.xml 如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>info.xyz</groupId>
    <artifactId>xyz-businessLogic</artifactId>
    <version>0.0.1</version>
    <packaging>bundle</packaging>

    <dependencies>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
            </plugin>
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <configuration>
                    <instructions>
                        <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
                        <Bundle-Version>${project.version}</Bundle-Version>
                        <Import-Package>
                        </Import-Package>
                        <Export-Package>
                            info.xyz.common,
                            info.xyz.common.impl
                        </Export-Package>
                    </instructions>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

很明显,我的简单包的依赖项为零,并且导出了包含 Calculator 和 CalculatorImpl 文件的包。下面是用于定义这些服务的 blueprint.xml 文件。

<?xml version="1.0" encoding="UTF-8"?>
<blueprint default-activation="eager" xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jpa="http://aries.apache.org/xmlns/jpa/v1.0.0" xmlns:tx="http://aries.apache.org/xmlns/transactions/v1.0.0"

    xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0 
            http://www.w3.org/2001/XMLSchema-instance http://www.w3.org/2001/XMLSchema-instance 
            http://aries.apache.org/xmlns/jpa/v1.0.0 http://aries.apache.org/xmlns/jpa/v1.0.0 
            http://aries.apache.org/xmlns/transactions/v1.0.0 http://aries.apache.org/xmlns/transactions/v1.0.0">

    <bean id="calculatorService" class="info.xyz.common.impl.CalculatorImpl" />
    <service ref="calculatorService" interface="info.xyz.common.Calculator" />
</blueprint>

接下来,我的 PaxExam OSGI 容器的 pom.xml 如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>info.xyz</groupId>
    <artifactId>xyz-test-osgi</artifactId>
    <version>0.0.1</version>

    <parent>
        <groupId>info.xyz</groupId>
        <artifactId>xyz</artifactId>
        <version>0.0.1</version>
        <relativePath>../xyz</relativePath>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.ops4j.pax.exam</groupId>
            <artifactId>pax-exam-container-native</artifactId>
            <version>${pax.exam.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.ops4j.pax.exam</groupId>
            <artifactId>pax-exam-junit4</artifactId>
            <version>${pax.exam.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.ops4j.pax.exam</groupId>
            <artifactId>pax-exam-link-mvn</artifactId>
            <version>${pax.exam.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.ops4j.pax.url</groupId>
            <artifactId>pax-url-aether</artifactId>
            <version>${pax.url.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.ops4j.pax.exam</groupId>
            <artifactId>pax-exam</artifactId>
            <version>${pax.exam.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.ops4j.pax.exam</groupId>
            <artifactId>pax-exam-inject</artifactId>
            <version>${pax.exam.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.felix</groupId>
            <artifactId>org.apache.felix.framework</artifactId>
            <version>5.4.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>${ch.qos.logback.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>${ch.qos.logback.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>${javax.inject.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>

        <!-- Testing target -->
        <dependency>
            <groupId>info.xyz</groupId>
            <artifactId>xyz-businessLogic</artifactId>
            <version>0.0.1</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!-- Needed if you use versionAsInProject() -->
            <plugin>
                <groupId>org.apache.servicemix.tooling</groupId>
                <artifactId>depends-maven-plugin</artifactId>
                <version>1.3.1</version>
                <executions>
                    <execution>
                        <id>generate-depends-file</id>
                        <goals>
                            <goal>generate-depends-file</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

最后给出OSGI Test类如下:

package info.xyz.test.osgi;

import static org.ops4j.pax.exam.CoreOptions.junitBundles;
import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
import info.xyz.common.Calculator;

import javax.inject.Inject;

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.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;

@RunWith(PaxExam.class)
@ExamReactorStrategy(PerMethod.class)
public class OsgiTestClient
{
    @Inject
    protected Calculator _calculator;

    @ProbeBuilder
    public TestProbeBuilder probeConfiguration(TestProbeBuilder probe)
    {
        System.out.println("TestProbeBuilder gets called");
        probe.setHeader(Constants.DYNAMICIMPORT_PACKAGE, "*");
        probe.setHeader(Constants.IMPORT_PACKAGE, "info.xyz.common");
        probe.setHeader(Constants.IMPORT_PACKAGE, "info.xyz.common.impl");
        return probe;
    }

    @Configuration
    public Option[] config()
    {
        return new Option[] {
                junitBundles(),
                mavenBundle().groupId("info.xyz").artifactId("xyz-businessLogic").versionAsInProject(),
        };
    }

    @Test
    public void testAdd()
    {
        info.xyz.common.impl.CalculatorImpl calculator = new info.xyz.common.impl.CalculatorImpl();
        int result = calculator.add(1, 2);
        System.out.println("--- testing: ");
    }
}

最后一条评论,如果我注释掉注入 CalculatorService 的代码,代码运行良好(因为我手动实例化 CalculatorImpl 类)。因此,我的测试容器确实对 Calculator 接口和实现具有编译时和运行时可见性。但是注入此服务不起作用。

最后提醒一下,当我构建 PaxExam Karaf 测试容器时,Calculator 服务的注入是成功的,并且测试用例运行良好。错误是在运行本文中描述的 PaxExam OSGI 容器时发生的。

4

1 回答 1

2

是的,那么蓝图堆栈/库默认情况下没有安装在本机容器中(但它们在 Karaf 中)。

您需要将此 deps 添加到您的测试 pom 中:

    <dependency>
        <groupId>org.apache.aries</groupId>
        <artifactId>org.apache.aries.util</artifactId>
        <version>1.1.0</version>
    </dependency>

    <dependency>
        <groupId>org.apache.aries.proxy</groupId>
        <artifactId>org.apache.aries.proxy.api</artifactId>
        <version>1.0.1</version>
    </dependency>

    <dependency>
        <groupId>org.apache.aries.proxy</groupId>
        <artifactId>org.apache.aries.proxy.impl</artifactId>
        <version>1.0.4</version>
    </dependency>


    <dependency>
        <groupId>org.apache.aries.blueprint</groupId>
        <artifactId>org.apache.aries.blueprint.api</artifactId>
        <version>1.0.1</version>
    </dependency>

    <dependency>
        <groupId>org.apache.aries.blueprint</groupId>
        <artifactId>org.apache.aries.blueprint.core</artifactId>
        <version>1.4.2</version>
    </dependency>

    <dependency>
        <groupId>org.apache.aries.blueprint</groupId>
        <artifactId>org.apache.aries.blueprint.core.compatibility</artifactId>
        <version>1.0.0</version>
    </dependency>

    <dependency>
        <groupId>org.apache.aries.blueprint</groupId>
        <artifactId>org.apache.aries.blueprint.cm</artifactId>
        <version>1.0.5</version>
    </dependency>

并在您的测试中将以下捆绑包添加到您的配置中:

mavenBundle().groupId("org.apache.aries").artifactId("org.apache.aries.util").versionAsInProject(),
                    mavenBundle().groupId("org.apache.aries.proxy").artifactId("org.apache.aries.proxy.api").versionAsInProject(),
                    mavenBundle().groupId("org.apache.aries.proxy").artifactId("org.apache.aries.proxy.impl").versionAsInProject(),
                    mavenBundle().groupId("org.apache.aries.blueprint").artifactId("org.apache.aries.blueprint.api").versionAsInProject(),
                    mavenBundle().groupId("org.apache.aries.blueprint").artifactId("org.apache.aries.blueprint.cm").versionAsInProject(),
                    mavenBundle().groupId("org.apache.aries.blueprint").artifactId("org.apache.aries.blueprint.core").versionAsInProject(),
                    mavenBundle().groupId("org.apache.aries.blueprint").artifactId("org.apache.aries.blueprint.core.compatibility").versionAsInProject().noStart(),

这应该是诀窍!

于 2015-12-15T17:51:36.217 回答