似乎可以用源代码生成器生成用于单元测试的代理方法
对于类中的非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的情况下就不会对当前代码的编译结果有任何影响。
完美(