C# 如何构造这个类,以便尽可能多地进行单元测试?

C# 如何构造这个类,以便尽可能多地进行单元测试?,c#,unit-testing,C#,Unit Testing,晚上好, 我正在努力了解单元测试,在单元测试转变为集成测试之前,我很难确定我能把它推进多远 我现在正在处理的项目中的一个示例:它有一个类,使用DirectorySearcher对Active Directory执行LDAP搜索,并将结果作为Person对象返回。我的第一个倾向是为DirectorySearcher获取接口,然后创建一个相当复杂的存根,用于测试。然而,这被证明是有问题的,因为DirectorySearcher似乎没有使用接口,并且需要大量代码才能成功地将其删除 我的下一个想法是创建

晚上好,

我正在努力了解单元测试,在单元测试转变为集成测试之前,我很难确定我能把它推进多远

我现在正在处理的项目中的一个示例:它有一个类,使用DirectorySearcher对Active Directory执行LDAP搜索,并将结果作为Person对象返回。我的第一个倾向是为DirectorySearcher获取接口,然后创建一个相当复杂的存根,用于测试。然而,这被证明是有问题的,因为DirectorySearcher似乎没有使用接口,并且需要大量代码才能成功地将其删除

我的下一个想法是创建一个在内部使用DirectorySearcher的Searcher类,它可以让我测试LDAP结果和Person对象映射之间的映射,但这并没有让我受益匪浅,这是另一个抽象层次

所以我想底线是:有没有一种方法可以让我用单元测试来完成大部分工作?我真的希望集成测试套件尽可能小,因为我必须针对不断变化的外部数据源进行测试。我怀疑这是有规律的,但我一直没能找到


谢谢

如果您有一个不能依赖注入的类,那么最好的模式是创建一个包装器对象并包装该对象。然后,您可以注入您的包装(或包装的模拟)以获得该功能


因此,在您的例子中,创建一个包装器“Searcher”类是正确的,该类在内部调用DirectorySearcher。无论需要在DirectorySearcher上调用什么方法,都可以在Searcher类上提供虚拟方法。然后,您可以使用重写的方法创建一个模拟搜索器类,并在单元测试时注入该类(或者,让Moq为您创建它!)

如果您有一个不能依赖项注入的类,那么最好的模式是创建一个包装器对象并包装该对象。然后,您可以注入您的包装(或包装的模拟)以获得该功能


因此,在您的例子中,创建一个包装器“Searcher”类是正确的,该类在内部调用DirectorySearcher。无论需要在DirectorySearcher上调用什么方法,都可以在Searcher类上提供虚拟方法。然后,您可以使用重写的方法创建一个模拟搜索器类,并在单元测试时注入该类(或者,让Moq为您创建它!)

您应该为搜索器创建自己的接口,然后将搜索器对象封装在实现它的类中,这样您就可以依赖性注入存根,或者mock。

您应该为搜索者创建自己的接口,然后将搜索者对象封装在实现它的类中,这样您就可以依赖注入存根,或者mock。

据我所知,您的类(为了便于讨论,我们将其命名为“PeoplePerson”)需要根据特定标准抓取/接触人员。所以可以肯定地说,您的类需要一个PeopleRepository。稍后,我们将担心PeopleRepository如何能够为诸如“GetPeople(criteria)”之类的调用提供服务。现在,如果您测试PeoplePerson的开发,您很快就会发现正确的接口成员(他们通常是技术/实现不可知论者)。使用模拟框架(我假设LDAP会使您的单元测试变慢)将模拟注入PeoplePerson

公众人物 存储库){…//缓存它}

现在弄清楚如何实现ipeoperepository上的每个方法。为PeopleRepository编写测试,该测试针对包装已知数据集的真实ActiveServer/LDAP提供程序。这些测试会很慢(测试与ActiveServer集成的集成测试),但它们让其他人不用担心LDAP/ActiveServer


我发现创建抽象是一项很好的投资。

据我所知,您的类(为了便于讨论,我们将其命名为“PeoplePerson”)需要根据特定的标准抓取/接触到人。所以可以肯定地说,您的类需要一个PeopleRepository。稍后,我们将担心PeopleRepository如何能够为诸如“GetPeople(criteria)”之类的调用提供服务。现在,如果您测试PeoplePerson的开发,您很快就会发现正确的接口成员(他们通常是技术/实现不可知论者)。使用模拟框架(我假设LDAP会使您的单元测试变慢)将模拟注入PeoplePerson

公众人物 存储库){…//缓存它}

现在弄清楚如何实现ipeoperepository上的每个方法。为PeopleRepository编写测试,该测试针对包装已知数据集的真实ActiveServer/LDAP提供程序。这些测试会很慢(测试与ActiveServer集成的集成测试),但它们让其他人不用担心LDAP/ActiveServer


我发现创建抽象是一项很好的投资。

计算机科学中的所有问题都可以通过另一个间接层次来解决:p(我知道这没有帮助,但你问题中的一句话让我想起了这句话)。@Martin。。。“除了太多间接层次的问题”(感谢大卫·惠勒)计算机科学中的所有问题都可以通过另一个间接层次来解决:P(我知道这没有什么帮助,但你问题中的一句话让我想起了这句话)。@Martin。。。“除了间接层次太多的问题”(谢谢David Wheeler)谢谢,我很感激。我最头疼的事情之一是什么时候创建seam和单元测试,而不是仅仅放弃并进行集成测试。你有什么粗略的建议吗?基本上,当你有一些操作跨越了应用程序的边界时,如果