延續前篇【C#】小知識 #8 : 使用partial class + private內部類別,避免日後專案開發受限程度
筆者以單元測試做開發,發現使用非public內部類別
雖然可以減低日後維護限制,但是沒辦法直接做單元測試
,因為可見度問題。
雖然單元測試的意義以及封裝的用意"用戶原本就不需要了解,非public的行為"
,基本上我們不太希望把不該開放的類別或成員給外部的組件存取,但為了測試專案,不開放存取權限又很難做事,想要解決這問題:
舉例: 現在有一個類別裡面再包覆私有內部工具類別,想要做單元測試
public class MyClass
{
private class NestedClass
{
private static string CommonConcat(params string[] paras)
{
return $"{para1},{para2}";
}
}
}
邏輯:
AssemblyInfo.cs
[assembly:System.Runtime.CompilerServices.InternalsVisibleTo(測試專案名稱)]
internal
結果就可以看到單元測試能取得訪問權限,如圖片
邏輯:放寬准許protected
使繼承類別可以使用,如以下代碼
注意:不能測試實體類別,因為不能繼承。
namespace UnitTestProject
{
public class MyClass
{
protected class NestedClass
{
public static string CommondConcat(params string[] paras)
{
return string.Join(",", paras);
}
}
}
[TestClass]
public class TestClass : MyClass
{
[TestMethod]
public void CommondConcatTest()
{
var excepted = "Hello,ITHelp";
var result = MyClass.NestedClass.CommondConcat("Hello", "ITHelp");
Assert.AreEqual(excepted, result);
}
}
}
原先我是使用此方式,藉此直接呼叫非公開的內部類別,但是經過91老師
指點才知道錯得離譜。
這違反測試的核心意義:『應該以使用實際情境去考量』
,使用者正常不會
使用反射來呼叫該方式,這樣只會造成誤導、可讀性差。
另外如以下Code,可以發現呼叫方式是使用弱維護字串
,所以方法改名或是刪除無法在編譯前檢查
,這樣會造成後續維護困擾。
public static class NestedTypeHelper
{
public static object CallStaticNestedTypeMethod(System.Type type, string nestedClassName, string methodName, object[] parameters = null)
{
var nestedType = type.GetTypeInfo().DeclaredNestedTypes.SingleOrDefault(w => w.Name == nestedClassName);
var methodInfo = nestedType.DeclaredMethods.SingleOrDefault(w => w.Name == methodName);
return methodInfo.Invoke(null, parameters);
}
}
var result = CallStaticNestedTypeMethod(type: typeof(MyStaticObject), nestedClassName: "MyClass",
methodName: "CommonConcat", parameters: new[] { "Hello","ITHelp" });
Console.WriteLine(result); //結果:Hello,ITHelp
最後補上91老師的測試概念連結 : 連結請點擊 , 推薦讀者閱讀。