我正在使用Inside Out TDD开发应用程序,这是我在此过程中确定的步骤序列:
为A类基本功能编写测试
创建A类并实现所需的功能
为其他功能编写测试
在A类实施所需的功能
请注意,A类违反了SRP
提取服务类A使用
现在,我对此提出的一些问题"提取十字路口"是:
这假设在A类中注入B和C的依赖关系。我们应该对B和C或实例使用模拟吗?
如果我们应该使用B和C的实际实例,我们的单元测试现在是否测试多个单元并且它们不仅仅是单元测试(集成或可能是验收测试)?
另外,如果我们应该将一些原始单元测试(针对A)切换到测试B和C的功能,我发现它经常变得 很难写:< / em>
由于A和B / C之间传递的数据经常变得更加颗粒化并且难以设置。
答案 0 :(得分:2)
这是分裂一个类的代码成本的一个非常明确的陈述。此外,SRP很容易过度应用(任何具有多个陈述的程序显然都做了不止一件事,'责任'是一个可延展的术语。)
所以我会等待重构的时间比其他许多人还要长。不过,它最终会到期,所以......
当真正的课程很难设置,或者有真实的副作用时(对我而言,“太慢了”),我会嘲笑它。当它足够简单地使用课而不是模拟时,我没有注意到更多的脆弱性,这已经解决了我的担忧。
最后,我得出的论点是,他们不再是'单位'测试,但这也容易产生适得其反的分裂。类上的单个方法也是一个“单元”,所以我们不应该模拟它调用的任何其他方法吗?根据我的经验,几乎从来没有。我眼中的单元测试应该是务实的首先,理论上的纯度,最好是滞后的第二或第三。
答案 1 :(得分:1)
对我来说,TDD中外部的美妙之处在于,您最终会得到专注于所需行为的测试,而不是实施细节。
如果你想将你的类重构为几个类,那么我不会为这些新类创建单独的测试,因为更改是一个实现细节(特别是如果提取的类是内部的),就像你重构为单独的方法一样在同一个班。这种重构不应该改变行为,因此不需要改变。
当要重用类时,这会发生变化。在这种情况下,他们可能会转移到一个新的包,因此需要测试与它们一起移动,或者它们可能变得公开并直接从当前包中暴露出来,在这种情况下,他们可能需要更广泛的一套更全面的测试(特别是非快乐路径测试)。
如果您继续沿着为类编写测试1-1的路径,那么您最终将会遇到许多非常脆弱的测试,每次您想要重构代码时都需要更改这些测试,这些测试会非常快速地消失IMHO。