Visual Studio允许通过自动生成的访问器类对私有方法进行单元测试。我已经编写了一个私有方法的测试,它编译成功,但在运行时失败。一个相当小的版本的代码和测试是:
//in project MyProj
class TypeA
{
private List<TypeB> myList = new List<TypeB>();
private class TypeB
{
public TypeB()
{
}
}
public TypeA()
{
}
private void MyFunc()
{
//processing of myList that changes state of instance
}
}
//in project TestMyProj
public void MyFuncTest()
{
TypeA_Accessor target = new TypeA_Accessor();
//following line is the one that throws exception
target.myList.Add(new TypeA_Accessor.TypeB());
target.MyFunc();
//check changed state of target
}
运行时错误为:
Object of type System.Collections.Generic.List`1[MyProj.TypeA.TypeA_Accessor+TypeB]' cannot be converted to type 'System.Collections.Generic.List`1[MyProj.TypeA.TypeA+TypeB]'.
根据智能感知-因此我猜编译器-目标类型是TypeA_Accessor。但是在运行时它的类型是TypeA,因此列表添加失败。
有什么方法可以停止这个错误吗?或者,更有可能的是,其他人有什么其他的建议(我预测可能是“不要测试私有方法”和“不要使用单元测试来操纵对象的状态”)。
提取私有方法到另一个类,在该类上进行测试;阅读更多关于SRP原则(单一责任原则)
看起来你需要将私有方法提取到另一个类;在这方面应该是公开的。您应该测试另一个类的公共方法,而不是试图测试私有方法。
我们有以下场景:
Class A
+ outputFile: Stream
- _someLogic(arg1, arg2)
我们需要测试_someLogic;但A类似乎扮演了过多的角色(违反SRP原则);只需将其重构为两个类
Class A1
+ A1(logicHandler: A2) # take A2 for handle logic
+ outputFile: Stream
Class A2
+ someLogic(arg1, arg2)
这样就可以在A2上测试一些逻辑;在A1中,只需创建一些伪A2,然后注入到构造函数中,以测试A2被调用到名为someLogic的函数中。
提取私有方法到另一个类,在该类上进行测试;阅读更多关于SRP原则(单一责任原则)
看起来你需要将私有方法提取到另一个类;在这方面应该是公开的。您应该测试另一个类的公共方法,而不是试图测试私有方法。
我们有以下场景:
Class A
+ outputFile: Stream
- _someLogic(arg1, arg2)
我们需要测试_someLogic;但A类似乎扮演了过多的角色(违反SRP原则);只需将其重构为两个类
Class A1
+ A1(logicHandler: A2) # take A2 for handle logic
+ outputFile: Stream
Class A2
+ someLogic(arg1, arg2)
这样就可以在A2上测试一些逻辑;在A1中,只需创建一些伪A2,然后注入到构造函数中,以测试A2被调用到名为someLogic的函数中。
如果PrivateObject不可用,并且被测试的类不是密封类,则可以将想要公开的方法和属性设置为受保护的。在单元测试文件中创建一个带有内部方法的继承类,这些内部方法公开了测试中的私有方法/属性。
如果被测试的类是:
class MyClass{private string GetStr(string x, int y) => $"Success! {x} {y}";}
改为:
class MyClass{protected string GetStr(string x, int y) => $"Success! {x} {y}";}
在单元测试文件中创建一个继承类,如下所示:
class MyClassExposed: MyClass
{
internal string ExposedGetStr(string x, int y)
{
return base.GetStr(x, y);
}
}
现在您可以使用继承的类MyClassExposed来测试公开的方法和属性。