领先一步
VMware 提供培训和认证,以加速您的进步。
了解更多在 Spring 上下文中对某些类进行单元测试时,最让我恼火的事情之一就是用所有依赖项初始化它们。对于 Spring 框架扩展(如 FactoryBean 实现或 *Aware 实现)尤其如此。添加所有依赖项很麻烦,而且很容易忘记调用 bean 生命周期方法,例如来自 InitializingBean 的 afterPropertiesSet 方法。
Spring 用于单元测试的基础类提供了很大的帮助,但仍然有一些事情很棘手。例如,在许多情况下,需要消除自动装配的歧义,以便协作者获得正确的实现。此外,为了受益于生命周期执行,您必须测试来自当前配置的 bean 实例,这并不总是很方便。
我一直在使用一个简单的工具来简化单元测试中协作者的设置,我认为我会与一些人分享它。它提供了一个 bean 初始化器,可用于连接现有 bean 上的依赖项。
BeanInitializer 初始化一个 bean,添加依赖项,并在一个方法中执行生命周期回调。
public class InitializingTests extends TestCase {
private Collaborator collaborator;
public void setUp throws Exception {
super.setUp();
collaborator = new SimpleCollaborator();
}
public void testBeanWithSimpleDependencyOnThis() throws Exception {
Service bean = BeanInitializer.initialize(new ServiceImpl(), this);
assertNotNull(bean.getCollaborator());
}
}
BeanInitializer.initialize 方法的参数是要初始化的 bean,以及要设置在其上的属性源,在本例中是单元测试本身。来自 InitializingBean、BeanNameAware 等的生命周期回调在返回 bean 之前被调用。这很有用,因为可以在不更改单元测试的情况下添加或删除生命周期接口。
您也可以这样做
Service bean = BeanInitializer.initialize(new ServiceImpl(), new Collaborator());
或者这样
Service bean = BeanInitializer.initialize(new ServiceImpl(), new
Object[] { new Collaborator(), "valueOfOnlyStringProperty" } );
或者这样(例如,在使用 spring-mock 基础类的单元测试中)
Service bean = BeanInitializer.initialize(new ServiceImpl(),
new Collaborator(), applicationContext );
在最后一种情况下,显式协作者会覆盖 applicationContext 中具有相同接口的任何值,因此自动装配是明确的。这非常适合添加复杂服务类的模拟实现,其中 applicationContext 已经包含“真实”实现。请记住,Spring 单元测试基础类缓存 applicationContext 实例,因此这可能是提高单元测试效率的绝佳方法。
如果您有兴趣,我已经上传了代码(此处) - 它非常简单,但非常有用,希望如此。