晚上好,
我正在努力解决单元测试问题,我在确定在进行集成测试之前能够推进单元测试的程度方面遇到了一些麻烦。
我正在处理的项目的示例:它有一个类,使用DirectorySearcher对Active Directory执行LDAP搜索,并将结果作为Person对象返回。我的第一个倾向是获取DirectorySearcher的接口,然后创建一个相当复杂的存根,我可以用它进行测试。但是,这证明是有问题的,因为DirectorySearcher似乎没有使用接口,并且需要大量代码才能成功地将其存根。
我的下一个想法是创建一个内部使用DirectorySearcher的Searcher类,它可以让我测试LDAP结果和Person对象映射之间的映射,但这不会让我受益匪浅,它还是另一个抽象层次
所以我想底线是这样的:有没有一种结构方式,所以我可以完成单元测试的大部分工作?我真的宁愿保持集成测试套件尽可能小,因为我必须对不断变化的外部数据源进行测试。我怀疑有这样做的模式,但我找不到它。
谢谢!
答案 0 :(得分:5)
如果你有一个不能依赖注入的类,那么最好的模式是创建一个包装器对象并包装该对象。然后,您可以注入包装器(或包装器的模拟器)以获得该功能。
因此,在您的情况下,创建一个内部调用DirectorySearcher的包装器“Searcher”类是正确的。无论您需要在DirectorySearcher上调用哪种方法,都可以在Searcher类中提供虚拟方法。然后你可以创建一个带有覆盖方法的模拟搜索器类,并在单元测试时注入(或者让Moq为你创建它!)
答案 1 :(得分:1)
根据我的理解,您的班级(为了讨论而让我们将其命名为“PeoplePerson”)需要根据特定标准获取/接触人员。因此可以说你的课需要一个PeopleRepository。我们将担心PeopleRepository如何能够在以后为“GetPeople(标准)”之类的调用提供服务。现在,如果您测试开发PeoplePerson的开发,您很快就会发现正确的接口成员(并且它们通常倾向于技术/ impl。不可知)。使用模拟框架(我假设LDAP会使您的单元测试更慢)将模拟注入PeoplePerson
public PeoplePerson(IPeopleRepository 存储库){... //缓存它}
现在弄清楚如何实现IPeopleRepository上的每个方法。编写PeopleRepository的测试,该测试针对包装已知数据集的真实ActiveServer / LDAP提供程序。这些测试速度很慢(测试与ActiveServer集成的集成测试),但它们让其他人免于担心LDAP / ActiveServer。
我发现创造这种抽象是一项很好的投资。
答案 2 :(得分:0)
您应该为Searcher创建自己的界面,而不是将Searcher对象包装在实现它的类中,这样您就可以依赖注入您的存根或模拟。