2012-07-19 110 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