单元测试对应用程序中最小的可测试软件进行测试,以确定其行为是否如预期的那样。
被测试单元的大小没有严格定义,但是单元测试通常是在类级别或围绕一小组相关的类编写的。被测试的单元越小,使用单元测试来表达行为就越容易,因为单元的分支复杂性较低。
通常情况下,当一个模块应该被分解成独立的、更连贯的部分并分别进行测试时,编写单元测试的难度就会凸显出来。因此,单元测试除了是一种有用的测试策略外,还是一种强大的设计工具,特别是与测试驱动开发相结合时。
在单元测试中,您可以看到一个重要的区别,它基于被测试单元是否与它的合作者隔离。
社交单元测试的重点是通过观察模块状态的变化来测试模块的行为。这将被测试单元视为完全通过其接口进行测试的黑盒子。
独立单元测试关注对象及其依赖项之间的交互和协作,这些交互和协作被测试双精度副本所取代。
这些风格并不相互竞争,而是经常在同一个代码库中使用,以解决不同的测试问题。
这两种类型的单元测试在微服务中都扮演着重要的角色
服务通常是一个由管道和协调代码包围的丰富域。
领域逻辑通常表现为复杂的计算和状态转换的集合。因为这些类型的逻辑是高度基于状态的,所以尝试隔离单元几乎没有什么价值。这意味着,在可能的情况下,真实的域对象应该被用于被测试单元的所有合作者。
使用管道代码,很难将被测试单元与外部模块隔离,也很难针对状态变化进行测试。因此,使用测试双精度点更有效。
此级别单元测试的目的是验证用于产生请求或映射来自外部依赖项的响应的任何逻辑,而不是以集成的方式验证通信。因此,为协作者使用测试重复提供了一种以可靠和可重复的方式控制请求-响应周期的方法。
此级别的单元测试提供比集成测试更快的反馈,并且可以像外部依赖关系在特殊情况下那样,通过具有双重响应来强制发生错误。
协调逻辑更关心模块之间传递的消息,而不是那些模块内的任何复杂逻辑。使用测试副本允许验证传递的消息的详细信息,并保留响应,这样就可以从测试中指定模块内的通信流。
如果一段协调逻辑需要太多的双精度,这通常是一个很好的迹象,表明应该单独提取和测试某些概念。
随着服务规模的减小,管道和协调逻辑与复杂领域逻辑的比例会增加。类似地,有些服务将完全包含管道和协调逻辑,例如到不同技术的适配器或其他服务的聚合器。
在这种情况下,全面的单元测试可能不会奏效。其他级别的测试(如组件测试)可以提供更多的价值。
单元测试和测试的目的通常是约束被测试单元的行为。一个不幸的副作用是,有时测试也会限制实现。这通常表现为过度依赖基于模拟的方法。
经常质疑单元测试提供的价值与它在维护方面的成本或它对实现的限制是很重要的。通过这样做,可以保持测试套件的小、集中和高价值。
单独的单元测试并不能保证系统的行为
到目前为止,我们已经独立地很好地覆盖了系统的每个核心模块。然而,当这些模块一起工作形成一个完整的服务时,没有覆盖这些模块,也没有覆盖它们与远程依赖项之间的交互。
为了验证每个模块与协作者的正确交互,需要更粗粒度的测试。