測試protected方法
現在有一個類,其中包含一個protected方法:
public class SomeClass { protected int SomeMethod(string arg) { ... } }如果我們需要對這個protected方法進行單元測試,可以在測試代碼中準備一個輔助類型:
public class SomeClassForTest : SomeClass { public int PublicSomeMethod(string arg) { return this.SomeMethod(arg); } }于是在單元測試中,便可以通過調用PublicSomeMethod來測試基類的SomeMethod方法:
var testClass = new SomeClassForTest(); var result = testClass.PublicSomeMethod(null); Assert.Equal(0, result);非常簡單。
如果您覺得麻煩,也可以將SomeClass類中的SomeMethod方法改為protected internal,這樣便可以在InternalVisibleTo的測試程序集中使用了。不過,我覺得為單元測試而改變成員的訪問級別不是一個合適的做法。
對protected方法進行Mock
現在有一個類,其中有一個protected方法:
public class SomeClass { protected virtual int SomeMethod(string arg) { ... } }并且,某個被測試的方法接受SomeClass作為參數。雖然被測試的方法不會直接調用SomeMethod方法,但是SomeMethod的實現會影響到公開接口的表現形式。于是,我們需要對SomeMethod進行Mock或Stub。為此,我們同樣需要準備一個輔助類型:
public class MockSomeClass : SomeClass { protected override int SomeMethod(string arg) { return this.PublicSomeMethod(arg); } public virtual int PublicSomeMethod(string arg) { return base.SomeMethod(arg); } }在MockSomeClass中,我們覆蓋了基類的SomeMethod實現,使它調用了子類中公開的PublicSomeMethod方法,而PublicSomeMethod內部又調用了基類的SomeMethod方法。因此,如果您不去進行任何處理,那么MockSomeClass會保持SomeMethod的實現不變。而如果您需要對SomeMethod進行Mock或Stub的時候,便可以從PublicSomeMethod下手:
Mock<MockSomeClass> mockSomeClass = new Mock<MockSomeClass>() { CallBase = true }; mockSomeClass.Setup(c => c.PublicSomeMethod("123")).Returns(123); DoSomeTest(mockSomeClass.Object); // use the mock object也很容易。
為了可測試性
值得注意的是,為了“可測試性”,第二部分中的protected方法必須是virtual的,因為我們需要在子類中進行override。同理,Mock框架能夠輔助的方法也必須是virtual的,即使是一個public方法。那么,您覺得這是為了可測試性而做出的讓步嗎?或者換句話說,您覺得,一個不可以override的protected方法,但是會影響到其他公開接口的功能,這是不是一個合理的設計呢?如果這是一個合理的設計,又不想作出這樣的讓步……我們又該怎么做呢?
文章來源于領測軟件測試網 http://www.kjueaiud.com/