對於類中的非public方法,如果要進行單元測試就比較麻煩,因為單元測試專案裡通常不能正常訪問非public方法,此時解決方法一般有兩個:
一是把方法宣告為internal,然後將單元測試專案設定為友元程式集。
缺點是要改訪問修飾符,對於我這種強迫症很不友好(
二是用反射訪問。
缺點是介面要是改了反射程式碼得手動改,就很麻煩(而且對效能測試不夠友好)。
還有一種方法是宣告一個與介面相似的public方法作為“代理”,以此間接呼叫要測試的非public方法。
比如宣告一個public的Meow_Proxy呼叫Meow,外部要測試Meow就透過呼叫Meow_Proxy來測試
但同時其缺點綜合了法一和法二,首先一個一個新增/修改代理方法很麻煩,其次額外的奇怪程式碼對強迫症也不友好。
突然想到可以用原始碼生成器來完成這一工作,同時克服上述的兩個缺點 。
這個原始碼生成器的作用就是為每個打了GenerateUnitTestProxy特性的方法都生成一份代理方法。
首先最明顯的,由於程式碼是自動生成,所以有效規避了手動修改這些操作。
例如對於:
public partial class Cat
{
[GenerateUnitTestProxy]
private void Meow()
{
Console.WriteLine("Meow~ Meow~ Meow~");
}
[GenerateUnitTestProxy]
private T Add<T>(T x, T y) where T : IAdditionOperators<T, T, T>
{
return x + y;
}
}
生成如下代理:
partial class Cat
{
public void Meow_UTP() => Meow();
public T Add_UTP<T>(T x, T y) where T : IAdditionOperators<T, T, T> => Add(x, y);
}
這樣就可以在單元測試專案裡透過呼叫代理方法來測試Meow和Add:
public void TestMethod1()
{
var cat = new Cat();
cat.Meow_UTP();
int n = cat.Add_UTP(128, 128);
}
接下來,再為GenerateUnitTestProxyAttribute特性新增[Conditional("UNIT_TEST")]`特性,並在原始碼生成器中新增“如果沒有定義UNIT_TEST符號就跳過生成”的邏輯,這樣在沒有定義UNIT_TEST的情況下就不會對當前程式碼的編譯結果有任何影響。
完美(