0%

【Unit Test】重構 (一) 透過繼承解耦

將一個本來沒有單元測試的專案,改成能測試的狀態,通常第一個遇到的問題就是耦合太深,導致無法切開來模擬外部對象,大幅度改動又可能牽扯很多Method與Class,在沒有測試保護下,怕改到壞掉而不自知。

以下記錄第一種重構方式,讓測試能在安全的重構之下進行
範例Code:
原本的Legacy Code 
```csharp public class UnitTestSampleBase { public UnitTestSampleBase() { }
    public int WantUnitTestMethod()
    {
        //直接引用,導致無法隔離測試
        ThirdPartyObject tpObj = new ThirdPartyObject();

        int value =  tpObj.GetValue();

        return value + 1;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25


1. 分離耦合的部分

```csharp
public class UnitTestSampleBase
{
public UnitTestSampleBase() { }

protected virtual int GetValue()
{
//開一個virtual的Method,將外部引用隔離出來
ThirdPartyObject tpobj = new ThirdPartyObject();
return tpobj.GetValue();
}

public int WantUnitTestMethod()
{
//避免直接引用
int value = GetValue();

return value + 1;
}
}

  1. 做一個Fake的受測對象,並繼承受測得目標,並改寫取得外部資源的結果的Method,讓它回傳我們寫死的固定值 ```csharp
    public class UnitTestSampleFake : UnitTestSampleBase
    {
     protected override int GetValue()
     {
         return 1;
     }
    
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19


3. 進行測試 ```csharp
[TestClass]
public class UnitTestSampleFakeTest
{
[TestMethod]
public void WantUnitTestMethod_Call_ShouldRetuen2()
{
//arrange
var sut = new UnitTestSampleFake();
//act
var actual = sut.WantUnitTestMethod();
//assert
//1+1 = 2
Assert.AreEqual(actual, 2);
}
}

  1. 測試通過

這樣對於外部使用你的Mthod的人來說,他Code都不用改(因為你還是保有原本的Method
WantUnitTestMethod,且不需要額外的外部注入或參數注入),但你的Code已經做了初步的分離跟測試,之後就可以慢慢在這個測試保護的基礎之上,繼續後續的開發了!!