[英]Are single implementer interfaces for unit testing an antipattern?
关于单元测试,我被告知生产代码中不应包含与测试相关的代码。
好吧,我觉得每次尝试进行单元测试时我都违反了规则。
我的程序集内部有一个类, Xyzzy
。 我希望依赖将它注入另一个类,然后将其存根,以便我可以IXyzzy
测试另一个类,所以我创建了一个接口, IXyzzy
。 哎呀,现在我的代码在生产中真正只用于测试。 更糟糕的是,我有点违背了什么界面(描述了实施者可以做什么 ,而不是它是什么)。 Xyzzy的公共界面和IXyzzy完全相同,没有其他人(除了存根)实现IXyzzy。
这对我来说似乎是一件坏事。
我可以创建一个抽象基类或者创建我想要在Xyzzy Overridable
/ virtual
上测试的所有公共方法,但是由于Xyzzy不是为继承而设计的,并且从YAGNI角度来看,它也不会继承。
是否仅为了测试反模式而创建单实施者接口? 还有更好的选择吗?
拥有仅用于测试的代码并没有错。 这实际上是正常的,就像生产代码包含仅用于调试和生产监控的功能一样。 没有明确的理由不允许这样做。 代码应该支持应用程序生命周期的所有方面。 测试只是生命周期的另一部分。
从这个意义上说,使用接口的方法是正确的。 如果您使生产应用程序的其余部分也使用接口(而不是具体类,尽管只有一个),它在架构上是合理的。
我有点违背了什么界面(描述了一个实现者可以做什么,而不是它是什么)
我没有明白你的意思,因为界面确实描述了对象可以做什么。 只有一个具体(生产)实现不会破坏此属性。
如果你仔细想想,每个类都有一个松散意义上的“接口”:所有方法的公共签名都暴露了一个类支持外部的接口。 是否实现.NET接口只是一个细节。 班级仍然向外界做出同样的承诺。
根据我的经验,这是.NET开发的典型特征,源于方法覆盖是在选择加入的基础上; 如果要模拟依赖项,则需要一个接口或一个方法都是虚拟的对象。
在像Java这样的语言中,每个方法都是可覆盖的,单实现接口确实是一个反模式,好的开发人员会把它叫出来。
继续做你正在做的事情 - 在我看来,无论你犯下什么罪,都要轻易胜过你单位测试的好处!
是的,这是一种反模式。 模式将是“某种情境中常见问题的解决方案”。 但是,在这种情况下,我们得到的是一个变通 ,而不是一个解决方案。
问题是需要将一个要测试的单元与其某些依赖项隔离开来,这样在编写单元测试时就不必考虑这些依赖项的实现。 这个问题的一般和真正的解决方案称为“模拟”,其中测试编写者可以指定模拟依赖项所需的任何行为。
相反,强制开发人员创建不必要的单独接口,或将方法声明为virtual
,只是技术上无法将单元与其他单元完全隔离的解决方法。
对于.NET,有几种提供此隔离功能的模拟工具,即TypeMock Isolator,JustMock和MS Fakes。 其他语言/平台(包括Java,Ruby和Python)都有自己类似表达能力的工具。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.