2013-02-14 16 views
1

所以,我一直在閱讀有效地使用遺留代碼。這很棒,涵蓋了許多很酷的技術,這些技術對未經測試的代碼也是「安全」的。從你打算測試的類繼承是否總是次優的?

我最喜歡的部分之一是建議擴展你打算測試的類,當有麻煩的依賴關係時。例如

class FooBar 
{ 
    public List<Foo> ReadFoos() 
    { 
    var s=new SqlConnection(Config.SomeConntectionStirng); 
    s.Read("Foo").... 
    } 
} 

被重構到

class FooBar 
{ 
    public List<Foo> ReadFoos() 
    { 
    var s=MyConnection(); 
    s.Read("Foo").... 
    } 
    protected virtual IConnection MyConnection() 
    { 
    return new SqlConnection(Config.SomeConnectionString); 
    } 
} 

然後去測試它,你會繼承它,像這樣:

class TestableFooBar : FooBar 
{ 
    protected override IConnection MyConnection() 
    { 
    return new MockConnection(); 
    } 
} 

和測試後擴展的類。

現在,我的問題。這可以做,而不是以後重構?我這樣說的主要原因是因爲這可能對於一些難以進行單元測試而不使調用API更難使用的代碼有用。在公共API上,你絕對希望它儘可能簡單。那麼,這是保持副設計的好方法嗎?

+0

你沒有使用依賴注入的原因?這基本上是它的存在理由。 – 2013-02-14 22:18:31

+1

@KirkWoll,基於他正在閱讀的書和他的問題文本,他正試圖從大概可怕的,不可測試的遺留代碼轉向更清潔的東西。這通常是一個以許多小增量完成的過程。 – 2013-02-14 22:35:08

+0

@安東伯格啊,好點。忽略了他所引用的這本書的主題。 – 2013-02-14 22:36:54

回答

5

從設計的角度來看,「提取物和覆蓋」可能不是在那裏你會選擇結束,但它歸結爲你的預算,改變現有的代碼,對工作增加新的功能。雖然您也可能不熱衷於更改公共API,但有技術可以保留API,同時還允許更合適的依賴注入。我相信這本書討論了一種這樣的技術,它是一種爲重載提供依賴的默認構造函數(下面的示例),另一種可以簡單地使用依賴注入容器。

public class Foo 
{ 
    IDependency dependency; 

    public Foo() // preserves API 
      : this(new Dependency()) 
    { 
    } 

    internal Foo(IDependency dependency) 
    { 
     this.dependency = dependency; 
    } 

注:在此示例中,我標誌着第二構造函數內部,但你可以把它作爲公衆,特別是如果你想你的程序集之外班有提供相關性的選項。對於簡單的可測試性,我喜歡內部修飾符,因爲我會通過「InternalsVisibleTo」程序集屬性將內部結構公開給我的單元測試項目。這可以讓你保持你的API清潔,但也有這種技術,但也有內部幫助類的最大可測性。