当一个类实现一个接口时,很容易模拟,但是,你必须为它创建一个接口。
您也可以通过子类化和覆盖进行模拟。如果您的基类提供了无参数保护的构造函数,那么您的子类mocks不会与基类构造函数中的更改绑定。
乍一看,似乎创建模拟的子类化方法比为所有内容创建接口更令人满意,但很明显,这并不是大多数人这样做的。
那么,为什么基于接口的模拟被认为比基于子类的模拟更好?
答案 0 :(得分:5)
与大多数信念相反,即使您进行测试驱动开发(TDD),您仍应遵循良好的设计实践。诀窍是使API可测试和精心设计。 TDD isn't a design methodology,但是反馈技术。
因此,这不是Interface Mocks 与Subclass Mocks 的问题,而是接口与子类的问题。
这是一个非常古老的讨论,应该在1994年结束;在Design Patterns中,我们了解到我们应该赞成合成优于继承。
关于这个主题有很长时间的讨论,但简而言之,在具有单一继承的语言中,基于继承的API设计是为了限制所有未来与其他(但无法预见的)维度的可变性。这种语言的继承过于严格。由于所有主要的面向对象语言(Java,C#,Ruby)都具有单一继承,因此您应该看到大多数面向对象的代码库正确地避免了继承。
当设计基于组合而不是继承时,如果你使用模拟对象,那么你将模拟接口,而不是基类。
答案 1 :(得分:2)
当您进行子类型和覆盖时,您可能会遗漏覆盖其中一个应该覆盖的方法,并且实际运行“生产”代码,您希望将其与测试隔离开来。
模拟界面时,必须模拟其100%的行为。无论模拟没有明确说明什么,只会抛出异常,并迫使你解决它。