2009-06-17 45 views
3

所以我有,看起來像一個輔助方法如下:我需要測試助手/設置方法嗎?

private D GetInstanceOfD(string param1, int param2) 
{ 
    A a = new A(); 
    B a = new B(); 
    C c = new C(a,b, param1); 

    return new D(c, param2); 
} 

這只是一個方便的輔助方法,我可以叫搶一個特定的對象,我需要而不是記住我需要哪些依賴掛鉤以獲取我需要的對象。

我的第一個問題是:應該像這些方法進行測試?我能想到要測試這些類型的方法的唯一原因是確保使用正確的依賴關係並正確設置。

如果第一個問題的答案是肯定的,我的第二個問題是:如何?我目前正在使用NUnit和RhinoMocks,並試圖弄清楚這種方法如何被重構爲可測試的(好吧,是否應該測試這樣的東西!);顯然,依賴注入在這裏不起作用,因爲這個方法實際上創建了依賴關係!

或正在使用這種方法不好的做法,我應該做類似以下內容:

D d = new (new C(new A(), new B(), "string"), 1024); 

回答

1

首先,該方法是私人的,所以通常我會說測試可能不是直接用於該方法所必需的。即使它是真實代碼的輔助方法,而不是您的測試的助手,您可能只想通過公共接口間接測試它。第二,如果你確實想測試它 - 也許無論如何 - 你應該考慮使用工廠來創建對象,而不是直接實例化對象。使用工廠,並結合接口,將允許您將依賴關係抽象出來。只需將工廠注入包含此方法的類的構造函數中,並將其用作此方法內的屬性即可創建適當的對象。如果你走這條路線,你也可能會發現工廠也是創建D的邏輯的地方。

如果代碼是生產代碼,這肯定是我會採取的方向。下面的示例:

public class ObjectFactory 
{ 
    public virtual A CreateA() { return new A(); } 
    public virtual B CreateB() { return new B(); } 
    public virtual C CreateC(string str) { return new C(CreateA(), CreateB(), str); 
    public virtual D CreateD(string str, int num) 
    { 
     return new D(CreateC(str), num); 
    } 
} 


public class Foo 
{ 
    private ObjectFactory ObjectFactory { get; set; } 

    public Foo() : this(null) { } 
    public Foo(ObjectFactory factory) 
    { 
     this.ObjectFactory = factory ?? new ObjectFactory(); 
    } 

    public void Bar() 
    { 
     D objD = this.ObjectFactory.CreateD(param1, param2); 
    } 
} 

[TestMethod] 
public void TestBar() 
{ 
    var factory = MockRepository.GenerateMock<ObjectFactory>(); 
    var d = MockRepository.GenerateMock<D>(); 
    factory.Expect(f => f.CreateD("abc", 10)).Return(d); 

    var foo = new Foo(factory); 

    foo.Bar(); 

    factory.VerifyAllExpectations(); 
    d.VerifyAllExpectations(); 
} 
3

要回答你的第一個問題,是你應該測試這種方法。測試這種方法比編寫整篇文章要少得多,並且會爲您提供運輸代碼驗證。

在這方面取決於你打算做的方法。假設函數的合理行爲如下:

  • 如果我爲第一個參數傳遞null,會發生什麼?
  • 如果我傳遞第二個參數的負數,會發生什麼?
  • 在您期望的情況下,GetInstanceOfD會實際返回一個D嗎?
  • D是否具有給定輸入的正確值。
  • 如果C,A和B實例假設可以訪問,那麼情況如何?
+0

一般來說,我的私有方法是由於重構使代碼保持DRY或方法很小而產生的。在這種情況下,代碼實際上可能已經在重構之前通過現有測試進行了測試。在這種情況下,我通常不會直接爲此方法編寫測試,而是依賴現有測試和任何新的公共方法測試。情況並非總是如此,我對使用反射/訪問器測試的私有方法進行了一些測試,但通常情況下,我只測試公共接口,因此我的測試不會不必要地耦合到類的內部。 – tvanfosson 2009-06-17 03:10:50

2

當你遇到這樣的問題時,要記住的一件好事是讓事情瑣碎

設置方法需要微不足道。拆解方法需要微不足道。幫助者方法可以是非常平凡的 - 如果他們有自己的一套測試。

如果你的單元測試本身變得如此複雜需要來測試它們,你做錯了。

0

private方法通常是一個指標,他們並不需要,因爲你將要測試使用這些private方法的方法來直接測試。

該方法感覺它屬於工廠或生成器類,而不是私有方法。如果您將實例化代碼作爲私有方法隱藏起來,它將不會被優雅地測試。

1

您應該測試此方法。你應該測試它,因爲它可能會失敗;一個XP諺語是測試一切可能打破

現在,這並不意味着你必須爲它創建新的測試;它可以通過其他方法進行間接測試。如果它在重構期間被提取,那麼它可能已經被測試過了。

如果需要,測試它的一種方法是將其提取到一個輔助類中,它不會是私有的,並將其拆分爲幾個函數以便能夠注入依賴關係。

//--- don't write this, you'll probably regret it ;o) 
D d = new (new C(new A(), new B(), "string"), 1024);