是的,SOLID是设计易于测试的代码的一种非常好的方法。作为简短的入门:
S-单一责任原则: 一个对象应该只做一件事,并且应该是代码库中唯一可以做一件事的对象。例如,以一个领域类,例如一个发票。发票类应代表系统中使用的发票的数据结构和业务规则。它应该是代码库中唯一表示发票的类。可以进一步细分为说一种方法应该有一个目的,并且应该是代码库中满足此需求的唯一方法。
通过遵循该原理,可以减少必须编写的用于在不同对象上测试相同功能的测试次数,从而提高设计的可测试性,并且通常还会得到较小的功能,这些功能更容易单独进行测试。
O-开放/封闭原则: 一个类应该对扩展开放,但对变化不开放。一旦对象存在并正常工作,理想情况下,无需回到该对象进行更改以添加新功能。相反,应该通过派生对象或将新的或不同的依赖实现插入对象来扩展对象,以提供该新功能。这样可以避免回归。您可以在需要的时间和位置引入新功能,而无需更改对象的行为,因为该对象已在其他地方使用。
通过坚持这一原则,通常可以提高代码的容忍“ mo头”的能力,并且还可以避免不得不重写测试以预期新的行为。对象的所有现有测试仍应在未扩展的实现上运行,而使用扩展的实现对新功能的新测试也应运行。
L-Liskov替代原理: 依赖于B类的A类应该能够使用任何X:B,而无需了解它们之间的区别。基本上,这意味着您用作依赖项的任何行为都应具有与依赖类相同的行为。举一个简短的例子,假设您有一个公开Write(string)的IWriter接口,该接口由ConsoleWriter实现。现在,您必须改为写入文件,因此您可以创建FileWriter。这样做时,必须确保可以像ConsoleWriter一样使用FileWriter(这意味着依赖项可以与之交互的唯一方法是通过调用Write(string)),因此FileWriter可能需要这样做必须从依赖项以外的其他位置提供作业(例如要写入的路径和文件)。
这对于编写可测试的代码非常重要,因为符合LSP的设计可以在任何时候用“模拟”对象代替真实对象,而无需更改预期的行为,从而可以放心地对小段代码进行测试然后系统将使用插入的真实对象。
I接口隔离原则: 接口应具有尽可能少的方法,以提供接口定义的角色的功能。简而言之,与较小的较大接口相比,较小的接口更好。这是因为较大的接口有更多更改的原因,并且会导致代码库中其他不必要的更改。
遵守ISP协议可以降低被测系统和这些SUT依赖关系的复杂性,从而提高可测性。如果要测试的对象取决于公开DoOne(),DoTwo()和DoThree()的接口IDoThreeThings,则即使该对象仅使用DoTwo方法,也必须模拟实现所有这三种方法的对象。但是,如果对象仅依赖于IDoTwo(仅公开DoTwo),则可以更轻松地模拟具有该方法的对象。
D-Dependency Inversion Principle(D依赖性倒置原则):创建 和抽象绝对不应依赖于其他具体概念,而应依赖抽象。该原理直接加强了松耦合的宗旨。对象永远不必知道对象是什么。相反,它应该关心对象的作用。因此,在定义对象或方法的属性和参数时,总是比使用具体实现更优选使用接口和/或抽象基类。这样一来,您就可以将一种实现方式交换为另一种实现方式,而不必更改用法(如果您还遵循与DIP紧密联系的LSP)。
再次,这对于可测试性是巨大的,因为它允许您再次将依赖项的模拟实现而不是“生产”实现注入到要测试的对象中,同时仍以与之相同的形式测试对象在生产中。这是“独立”进行单元测试的关键。