似乎可以用原始碼生成器生成用於單元測試的代理方法

HiroMuraki發表於2024-11-20

對於類中的非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的情況下就不會對當前程式碼的編譯結果有任何影響。

完美(

相關文章