似乎可以用源代码生成器生成用于单元测试的代理方法

对于类中的非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的情况下就不会对当前代码的编译结果有任何影响。

完美(

posted @ 2024-11-20 18:25  HiroMuraki  阅读(2)  评论(0编辑  收藏  举报