2010-02-03 100 views
1

我有一個java類,它有一個使用Facade(Singleton)創建的靜態成員。可測試設計

 
Class A implements InterfaceA { 

private static DataStore db = DataStoreFacade.getInstance("BDB"); //singleton instance 

    public void save(final String key, final String val) { 
    db.save(key,val); 
    } 
}; 

這裏類A被用作webservice(無狀態bean)的成員變量。

我無法使用EasyMock測試此代碼,因爲無法覆蓋DataStore實例。

有兩種選擇。

  1. 有一個構造函數將DataStore的實例設置爲db成員變量。問題是我不希望webservice類知道哪個數據存儲實例已經創建。

  2. 提供一個額外的受保護的Set方法來覆蓋數據庫對象。這是我用來創建DataStore的Easy Mock對象並覆蓋成員變量的地方。這是否是正確的設計?

還有什麼其他的可能性?

回答

0

你是正確的,是不好的可測試性。使用依賴注入,不要去爲靜態變量:

 

public class A implements InterfaceA { 

    private DataStore db; 

    public A(DataStore db) { 
    this.db = db; 
    } 

... 

} 
 

注入或建立或者使用依賴注入框架(如春季),或在引導工廠代碼的地方建立自己的對象。

產品代碼:

 

new A(DataStoreFacade.getInstance("..."); 
 

測試代碼:

 

public void test_xxx(){ 
    DataStore db = EasyMock.createMock(DataStore.class); 
    //... do some expectations and replay(db) 
    InterfaceA a=new A(db); 
    //... 

} 
 
+0

這就是Facade類創建DataStore實例的方式。問題是類A的用戶需要知道我要隱藏哪個數據存儲實例。 例如在此實現中 A a = new A(DataStoreFacade.getInstance(「bdb」)); 正如我所提到的,A類是WebService包裝類的成員,我不希望該類知道要創建哪個實例。我希望這個邏輯成爲類A的一部分,而不是包裝類。 – rjoshi 2010-02-14 14:25:47

0

好了,原來的代碼已經測試。這裏是它的一個單元測試,用JMockit

@Test 
public void testSave(final DataStore mockDb) 
{ 
    final String key = "aKey"; 
    final String value = "aValue"; 

    new A().save(aKey, aValue); 

    new Verifications() 
    {{ 
     mockDb.save(key, value); 
    }}; 
} 

如果需要,DataStoreFacade類可太輕慢。

0

爲什麼不把DB成員的保護,並在測試項目中繼承,並重寫成員:

project 
{ 
    Class A 
    { 
     protected static db = ... 
     public void Save(...) { ... } 
    } 
} 

test_project 
{ 
    Class B : A 
    { 
     protected override static db = ... (create test db) 
    } 

    Class testB 
    { 
     public A a; 

     public void Setup() 
     { 
      this.a = new B(); 
     } 

     public void TearDown() 
     { 
      // delete a 
     } 

     public void TestSaveKey() 
     { 
      // test a 
     } 
    } 
} 

它仍然從消費者的代碼/庫藏,測試對象不弄亂生產代碼,並且行爲將被測試,就好像它是生產版本一樣。

要小心的是,這對具有靜態成員爲你的數據庫對象可能會導致您的測試的麻煩,如果它不是每次測試後正確地清理。*

  • 我知道,你可能已經知道這一點,但我這是完整的說。