单元测试——Objective-c中的TDD:属性/构造函数注入或方法混合



自从我开始使用TDD以来,我一直坚信它是编写良好的正确模式兼容代码的好方法,而不会强迫我的设计决策。我发现这在80%的情况下都是正确的,但在测试某些类型的对象时,由于某种原因,在实现中包装和隐藏对象时,我遇到了问题。

为了给你一个例子,让我们考虑一个MyLocationManager对象,它为我的对象提供了一个公共接口,并包装在NSLocationManager中。当我想测试这样一个对象时,我必须提供一个模拟NSLocationManager。

我当然有属性/构造函数注入方法,但这意味着添加一个属性,或一个构造函数参数,与对象,我只是想从其他对象隐藏:我已经创建了MyLocationManager包装和隐藏NSLocationManager,为什么我要暴露属性只是为了测试它?

我发现的一个方法是相当直接的方法swizzle NSLocationManager的方法,所以我可以用模拟方法交换方法的实际实现,但这似乎很不干净,我不知道它有多安全。

据我所知,不公开属性构造函数可能违反了德墨忒耳定律,但另一方面,我认为在objective-c中,这种模式的一些灵活性是可以接受的。

所以我的问题是,应该有任何方式我不清楚地看到采用属性/构造函数注入,或方法混用是一种常用的做法?

对于这个场景是否有其他我应该更好地使用的技术?

在脚注上:这个问题是真实的,即使对象包装网络代码和类,如NSUrlSession

在某种程度上,测试设置可能比要测试的代码更复杂,所以人们可能记得,测试是为了什么而发明的。

我认为一种实用的方法是,只在包含单独类延续的单独头文件中公开您需要的属性。

经过长时间的测试驱动开发经验,我发现我的这个老问题很容易回答。出于某种原因,我认为属性注入和依赖注入应该避免掩盖某些东西。我再也不这么想了。

在我最初的问题的前一个场景中,现在的我的正确答案是:

你必须暴露NSLocationManager的依赖,也许提供一个构造器注入器方法,和一个方便的构造器方法,用NSLocationManager初始化位置管理器。
没有必要隐藏依赖,即使它是一个包装器类,因为当你发现自己需要混合一些方法时,你正在破解对象的"内部"并在不测试接口的情况下对其进行调整,以一种不受控制的方式修改运行时行为。

如果你想要搅拌,那就向前搅拌,但这不是正确的选择。

最新更新