如何单元测试抽象类:使用存根扩展?
我想知道如何对抽象类和扩展抽象类的类进行单元测试。
我是否应该通过扩展抽象类来测试抽象类,抽出抽象方法,然后测试所有具体方法? 那么只测试我重写的方法,并测试单元测试中抽象类扩展对象的抽象方法?
我是否应该有一个可用于测试抽象类方法的抽象测试用例,并在扩展抽象类的对象的测试用例中扩展此类?
请注意,我的抽象类有一些具体的方法。
编写一个Mock对象,并将它们用于测试。 它们通常非常非常小(从抽象类继承),而不是更多。然后,在您的单元测试中,您可以调用您想要测试的抽象方法。
您应该测试包含您所有其他类的逻辑的抽象类。
抽象基类有两种使用方式。
您正在专门研究您的抽象对象,但所有客户端都将通过其基本接口使用派生类。
您正在使用抽象基类来分析设计中对象的重复,客户端通过自己的接口使用具体的实现。
1 - 策略模式的解决方案
如果你有第一种情况,那么你实际上有一个由派生类正在实现的抽象类中的虚方法定义的接口。
你应该考虑将它作为一个真正的接口,将你的抽象类改为具体的,并且在它的构造函数中接受这个接口的一个实例。 您的派生类然后成为这个新界面的实现。
这意味着您现在可以使用新接口的模拟实例以及现在的公共接口对每个新实现进行测试,以测试以前的抽象类。 一切都很简单,可测试。
解决方案2
如果你有第二种情况,那么你的抽象类就像一个帮助类一样工作。
看看它包含的功能。 看看是否有任何可以推到正在操作的对象上,以尽量减少这种重复。 如果还剩下任何东西,请将它作为一个助手类,让您的具体实现接受其构造函数并移除它们的基类。
这又会导致具体的类很简单并且易于测试。
作为规则
通过简单的复杂对象网络来支持简单对象的复杂网络。
可扩展可测试代码的关键是小型构建块和独立布线。
更新:如何处理两者的混合?
可以有一个基类执行这两种角色......即:它具有公共接口,并且具有受保护的辅助方法。 如果是这种情况,那么可以将辅助方法分解为一个类(方案2)并将继承树转换为策略模式。
如果你发现你有一些基类直接实现的方法,而其他的方法是虚拟的,那么你仍然可以将继承树转换为一个策略模式,但是我也会认为它是一个很好的指示,表明责任没有正确对齐,并且可能会需要重构。
更新2:抽象类作为垫脚石(2014/06/12)
有一天我使用了抽象的情况,所以我想探讨一下为什么。
我们的配置文件有一个标准格式。 这个特定的工具有3个配置文件,全部采用这种格式。 我希望每个设置文件都有一个强类型的类,所以通过依赖注入,类可以请求它关心的设置。
我通过拥有一个抽象基类实现了这一点,该基类知道如何解析暴露这些相同方法的设置文件格式和派生类,但封装了设置文件的位置。
我可以写一个3个类封装的“SettingsFileParser”,然后委托给基类来公开数据访问方法。 我选择不这样做,因为它会导致派生代码更多的3个派生类。
然而......随着代码的发展以及这些设置类的消费者变得更加清晰。 每个设置用户都会询问一些设置并以某种方式对它们进行转换(因为设置是文本,它们可以将它们包装在将它们转换为数字等的对象中)。 在发生这种情况时,我将开始将此逻辑提取到数据操作方法中,并将它们推回到强类型设置类中。 这将导致每一组设置的更高级别的界面,最终不再意识到它正在处理“设置”。
此时,强类型设置类将不再需要公开底层“设置”实现的“getter”方法。
在那一点上,我不再希望他们的公共接口包含设置访问器方法; 所以我将改变这个类来封装一个设置解析器类,而不是从它派生。
因此,抽象类是:我目前避免委派代码的一种方式,以及代码中的一个标记,以提醒我稍后更改设计。 我可能永远都不会这样做,所以它可能会活得很好......只有代码才能说明问题。
我发现这对任何规则都是正确的......比如“没有静态方法”或“没有私人方法”。 它们代表了代码中的气味......这很好。 它使您能够找到您错过的抽象概念,并让您在同一时间为您的客户提供价值。
我想像这样的规则定义了一个风景,其中可维护的代码存在于山谷中。 当你添加新的行为时,就像在你的代码上着陆一样。 最初,你把它放在任何地方..然后你重构,让优秀设计的力量推动行为,直到所有结果在山谷中。
我对抽象类和接口所做的工作如下:我编写一个测试,它使用对象,因为它是具体的。 但是X类型的变量(X是抽象类)在测试中没有设置。 这个测试类不会被添加到测试套件中,而是它的子类,它有一个设置方法,将变量设置为X的具体实现。这样我就不会复制测试代码。 未使用的测试的子类可以根据需要添加更多的测试方法。
链接地址: http://www.djcxy.com/p/61743.html上一篇: How to unit test abstract classes: extend with stubs?
下一篇: Crash after returning from Windows keyboard hook procedure