Spring Dynamic Modules测试框架源码分析

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】
免费领取10G资料包与项目实战视频资料

一.问题描述

在用spring-dm对某bundle进行测试时,报了如下错误。于是便对spring-osgi-test.jar中的几个测试类做了下研究。

        java.io.FileNotFoundException: C:\Users\boy\.m2\repository\org\aopalliance\com.springsource.org.aopalliance\1.0.0\com.springsource.org.aopalliance-1.0.0.jar (系统找不到指定的路径。)
            at java.io.FileInputStream.open(Native Method)
            at java.io.FileInputStream.<init>(FileInputStream.java:106)
            at org.springframework.core.io.FileSystemResource.getInputStream(FileSystemResource.java:110)
            at org.springframework.osgi.test.AbstractOsgiTests.installBundle(AbstractOsgiTests.java:323)
            at org.springframework.osgi.test.AbstractOsgiTests.startup(AbstractOsgiTests.java:253)
            at org.springframework.osgi.test.AbstractOsgiTests.prepareTestExecution(AbstractOsgiTests.java:374)
            at org.springframework.osgi.test.AbstractOsgiTests.runBare(AbstractOsgiTests.java:203)
            at org.springframework.osgi.test.AbstractOsgiTests$1.protect(AbstractOsgiTests.java:184)
            at junit.framework.TestResult.runProtected(TestResult.java:124)
            at org.springframework.osgi.test.AbstractOsgiTests.run(AbstractOsgiTests.java:181)

二.spring dm对bundle的集成测试

在使用spring dm框架时,其中的spring-osgi-test.jar这个bundle对集成测试提供了很好的支持。其中最重要的几个类如下

(1)AbstractOsgiTests.java

(2)AbstractConfigurableOsgiTests.java

(3)AbstractDependencyManagerTests

(4)AbstractConfigurableBundleCreatorTests

1.AbstractOsgiTests类

下面说下该类中比较重要的一个方法,在这个方法中定义了bundle的加载过程。


        private Resource[] locateBundles() {
                //获取测试框架所需的bundle
                Resource[] testFrameworkBundles = getTestFrameworkBundles();
                //获取要测试的bundle.
                Resource[] testBundles = getTestBundles();

                if (testFrameworkBundles == null)
                    testFrameworkBundles = new Resource[0];
                if (testBundles == null)
                    testBundles = new Resource[0];

                Resource[] allBundles = new Resource[testFrameworkBundles.length + testBundles.length];
                System.arraycopy(testFrameworkBundles, 0, allBundles, 0, testFrameworkBundles.length);
                System.arraycopy(testBundles, 0, allBundles, testFrameworkBundles.length, testBundles.length);
                return allBundles;
            }

其中的getTestFrameworkBundles()方法和getTestBundles()方法都由子类进行实现。对于getTestFrameworkBundles()方法,需要获取到测试框架所需的bundle。而对于getTestBundles()方法需要获取到要被测试的bundle.

2.AbstractDependencyManagerTests类

AbstractDependencyManagerTests是AbstractOsgiTests的子类,在其中提供了对getTestFrameworkBundles()方法的实现。

            protected Resource[] getTestFrameworkBundles() {
                    return locateBundles(getTestFrameworkBundlesNames());
            }

在这个getTestFrameworkBundlesNames()方法中,会获取测试框架所需的bundle名称.默认情况下,会加载spring-osgi-test.jar中的boot-bundles.properties文件中指定的bundle.如果子类要更换测试框架所需的bundle,可重载AbstractDependencyManagerTests中的getTestingFrameworkBundlesConfiguration()方法。


            protected Resource[] locateBundles(String[] bundles) {
                    if (bundles == null)
                        bundles = new String[0];

                    Resource[] res = new Resource[bundles.length];
                    for (int i = 0; i < bundles.length; i++) {
                        res[i] = locateBundle(bundles[i]);
                    }
                    return res;
            }

            protected Resource locateBundle(String bundleId) {
                    Assert.hasText(bundleId, "bundleId should not be empty");

                    // parse the String
                    String[] artifactId = StringUtils.commaDelimitedListToStringArray(bundleId);

                    Assert.isTrue(artifactId.length >= 3, "the CSV string " + bundleId + " contains too few values");
                    // TODO: add a smarter mechanism which can handle 1 or 2 values CSVs
                    for (int i = 0; i < artifactId.length; i++) {
                        artifactId[i] = StringUtils.trimWhitespace(artifactId[i]);
                    }
                    //获取本地的maven仓储。
                    ArtifactLocator aLocator = getLocator();

                    return (artifactId.length == 3 ? aLocator.locateArtifact(artifactId[0], artifactId[1], artifactId[2])
                            : aLocator.locateArtifact(artifactId[0], artifactId[1], artifactId[2], artifactId[3]));
                }

在上面的方法中,测试框架会默认到本地的maven仓储中加载所需的bundle. 对于默认的maven仓储,如果用户没有修改过maven的setting.xml中的这项值/path/to/local/repo,则默认路径是:

${user.home}\.m2\repository这个目录下,对于我的机器则是C:\Users\boy\.m2\repository下。由于我修改了setting.xml中localRepository为 c:\repository,系统在加载bundle时还是会去C:\Users\boy\.m2\repository中寻找,我本地的maven仓储已经不是这个目录了,当然就会出现开头说的错误信息。

三.问题解决

对于上面的错误,我们已经知道了原因,最简单的一种修改方法是将maven中的setting.xml中的localRepository配置改回默认配置。但对于我而言,个人比较喜欢比较简短的文件路径,不想修改回默认的配置,哪就只好想别的办法。

在AbstractDependencyManagerTests类中,

        protected ArtifactLocator getLocator() {
            return locator;
        }

该方法是允许子类扩展的。Spring dm对ArtifactLocator提供的默认实现类是LocalFileSystemMavenRepository类。

该类不允许对maven中的repositoryHome进行设置。如果能有另一个实现ArtifactLocator接口的类且允许自已指定repositoryHome路径也可以灵活的解决上面的问题。下面是自定义的maven仓储定位器的实现:

        public class ConfigLocalFileSystemMavenRepository implements ArtifactLocator {

            /** discovered local m2 repository home */
            private String repositoryHome;

            public ConfigLocalFileSystemMavenRepository(String repositroyHome) {
                this.repositoryHome = repositroyHome;
            }

            //其它方法省略,省略的方法参见 LocalFileSystemMavenRepository中的实现。

        }

四.完整的测试代码如下:


        public class SpringDmSampleTest extends AbstractConfigurableBundleCreatorTests {

            @Override
            protected String[] getTestBundlesNames() {
                return new String[] { "com.mango.cache, cache.core, 1.0.0" };
            }

            @Override
            protected Resource getTestingFrameworkBundlesConfiguration() {
                return new InputStreamResource(SpringDmSampleTest.class
                        .getResourceAsStream("boot-bundles.properties"));
            }

            @Override
            protected ArtifactLocator getLocator() { ArtifactLocator locator = new ConfigLocalFileSystemMavenRepository( "c:/repository"); return locator; }

        }

对于要测试的bundle,一定要注意将它install到本地maven仓储中。

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » Spring Dynamic Modules测试框架源码分析

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏