2012-07-19 60 views
1

我有一个多模块项目,其中每个模块都有自己的单元测试,并为该模块的类提供模拟。在Spring上重新注册单例bean

我想建立一个应用程序上下文,其中每个模块可以定义自己的嘲笑,但后来的单元测试将能够覆盖这些嘲笑,例如:

public class Test { 

    private static final class StupidMock { 
    } 

    @org.junit.Test 
    public void test() { 
     StaticApplicationContext applicationContext = new StaticApplicationContext(); 
     final ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory(); 
     StupidMock stupidMock = new StupidMock(); // original mock 
     beanFactory.registerSingleton(StupidMock.class.getName(), stupidMock); 

     StupidMock f1 = applicationContext.getBean(StupidMock.class); 
     if (f1 == null || f1 != stupidMock) { // ensuring mock is retrievable 
      fail("Could not get bean"); 
     } 

     for (String names2Remove : beanFactory.getBeanNamesForType(StupidMock.class)) { 
      applicationContext.removeBeanDefinition(names2Remove); // <-- fails here 
     } 

     StupidMock stupidMock2 = new StupidMock();  // replacement mock 
     beanFactory.registerSingleton(StupidMock.class.getName(), stupidMock2); 
    } 
} 

的问题是,这个简单的代码片段尝试删除第一个模拟失败,声称没有这样的bean(尽管Spring已经成功地为我提供了一个名字)。

如果我只是试图在第一个模拟器上注册另一个模拟器,Spring会抱怨说已经存在对象绑定。

DefaultSingletonBeanRegistry有一个removeSingleton方法是受保护的,但我无法控制由StaticApplicationContext拥有的豆厂。无论如何,我可以使用反射并调用这个受保护的方法,但是对于这样一个简单的任务,这样做只是感觉不对。

我在做什么错?我如何在StaticApplicationContext上实现单身更换?

回答

2

这里的问题是,registerSingleton方法实际上不会创建相应的BeanDefinition,它只是注册实例化的单例,并将它与您提供的名称相关联,并在稍后通过应用程序Context获取它 - 但没有底层的BeanDefinition。

所以当你打电话时,applicationContext.removeBeanDefinition(names2Remove);它失败,因为没有bean definition,只有注册完全实例化的bean。

的解决方法是不使用registerSingleton,而是使用registerSingleton的形式使用的BeanDefinition:

Map<String, String> map = new HashMap<String, String>(); 
map.put("i", "10"); // set all the properties for the mock.. 
MutablePropertyValues propertyValues = new MutablePropertyValues(map); 

beanFactory.registerSingleton(StupidMock.class.getName(), StupidMock.class, propertyValues); 
+0

我已经通过提供自己的Application Context类来解决这个问题,它与StaticApplicationContext相同,但允许钩住自定义BeanFactory(原始StaticAppCtx不允许这样做)。这个自定义BF的唯一区别是它不会在单例重新注册时发生抱怨。非常感谢您的提示,我已经学到了很多关于Spring的知识:) – mindas 2012-07-20 10:31:17

1

如果你正在使用Spring框架你为什么不使用Spring testing framework

您可以使用以下注释具有特定嘲笑每个单元测试的基础上

@ContextConfiguration 
@RunWith(SpringJUnit4ClassRunner.class) 
2

您可以spring-reinject重新定义一个bean。

+0

有趣的项目,谢谢! – mindas 2014-02-03 08:06:30

相关问题