OSGi在集成测试中的应用

最近对测试(集成测试+单元测试)代码进行了一下重构, 导致很多以前运行通过的测试现在都无法通过了, 由于我们的test case在测试前需要加载一堆spring配置文件, 而这个加载过程耗尽了99%的测试时间, 无尽的等待实在让人心烦. 虽然使用TestSuite可以对这些spring配置文件只需要加载一次, 但是如果需要对一个个的testcase进行单个调试修改的话, 就比较耗时了.
当然我们的测试也需要调整, 现在的spring配置文件耦合还是比较紧, 导致某一个测试需要依赖一些无关的bean, 虽然我们采用了spring bean的延迟加载策略, 但是依然是杯水车薪, 效果不是很明显.
好吧, 转入正题, 这里我们需要利用OSGi的动态加载和热替换特性, 将test case与spring container采用bundle的组织形式进行分离. 然后测试和spring container在OSGi容器中运行. 这样当我们需要对单个test case运行的时候就不再需要加载spring container了, 直接使用bundle中的spring container了.除非对spring container中的bean进行了修改需要重启加载spring container之外, 其他时候则不需要重启之. 对test case也采用同样的处理方式, 这样可以采用边改边测. 大幅度的提高了修改test case的效率.

下面说说大致做法
首先将spring 配置相关的东东使用一个bundle封装起来, 并对外提供一个类似这样的暴露接口:
public interface SpringContext {
public ApplicationContext getApplicationContext();
}

并实现一个对外提供服务的Activator:
public class SpringContextActivator implements BundleActivator {
private ServiceRegistration sf;

public void start(final BundleContext context) throws Exception {
sf = context.registerService(SpringContext.class.getName(), new SpringContextImpl(), null);
}
public void stop(BundleContext context) throws Exception {
sf.unregister();
}
}

然后将test case用另外一个bundle进行封装, 也就是将原有的工程转换成plug-in工程. 这里我们采用的测试框架是Unitils 3.1, 需要对SpringModule进行重载, 改写其中创建ApplicationContext的过程:
public class OsgiSpringModule extends SpringModule {
@Override
public boolean isApplicationContextConfiguredFor(Object testObject) {
return true;
}
@Override
public void invalidateApplicationContext(Class<?>... classes) {
}
@Override
public void init(Properties configuration) {
}
@Override
public ApplicationContext getApplicationContext(Object testObject) {
return SpringContextHolder.get();
}
}

然后提供一个执行指定测试类的Activator:
public class TestActivator implements BundleActivator {
private static final Log logger = LogFactory.getLog(TestActivator.class);
private ServiceReference sr;
public void start(BundleContext context) throws Exception {
sr = context.getServiceReference(SpringContext.class.getName());
SpringContext ctx = (SpringContext) context.getService(sr);
SprongContextHolder.set(ctx.getApplicationContext());
//执行指定测试类或方法...
}
public void stop(BundleContext context) throws Exception {
SpringContextHolder.remove();
}
}

怎么通过代码方式来执行指定的类和方法, [url=http://macrochen.iteye.com/blog/550202]这里[/url]我有写, 可以参考下.
同时使用了一个SpringContextHolder, 用来在Activator和SpringModule之间传递ApplicationContext:
public class SpringContextHolder {
public static ThreadLocal<ApplicationContext> inner = new ThreadLocal<ApplicationContext>();

public static ApplicationContext get() {
return inner.get();
}

public static void set(ApplicationContext value) {
inner.set(value);
}

public static void remove() {
inner.remove();
}
}

另外使用到了DataSet, 而里面的测试数据的路径也需要改写, 以前采用是与测试文件同路径, 当采用OSGi之后, 路径全变了, 采用的是bundleresources协议的URL, 而原有test采用的是file协议的URL, 因此需要在二者之间进行一个转换.具体做法我已经在[url=http://macrochen.iteye.com/blog/550200]OSGi小结[/url]里面进行了说明.

这些就是大致的做法, 里面还有一些细节需要注意, 否则很难跑起来:(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值