Spring Dynamic Modules测试框架源码分析

 

一.问题描述

在用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中的这项值<localRepository>/path/to/local/repo</localRepository> ,则默认路径是:

${user.home}\.m2\repository这个目录下,对于我的机器则是C:\Users\boy\.m2\repository下。由于我修改了setting.xml中localRepository为 <localRepository>c:\repository</localRepository>,系统在加载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仓储中。

 

 

 

 

 

 

 

 

 

 

 

 

 

    原文作者:Spring Cloud
    原文地址: https://blog.csdn.net/yfzzky/article/details/84278436
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞