Objective-c 中的 TDD:property/constructor 注入或方法混合?
TDD in Objective-c: property/constructor injection or method swizzling?
自从我开始使用 TDD 以来,我一直坚信这是编写正确的模式兼容代码的好方法,而无需强制我的设计决策。
我发现在 80% 的情况下都是如此,但是在测试某些对象时遇到问题,由于某种原因,这些对象在实现中包装和隐藏了一个对象。
举个例子让我们考虑一个 MyLocationManager 对象,它为我要使用的对象提供一个通用接口,并包装在 NSLocationManager。
当我想测试这样的对象时,我当然必须提供一个模拟的 NSLocationManager。
我当然有 property/constructor 注入方法,但这意味着添加一个 属性 或构造函数参数,其中包含一个我只想对其他对象隐藏的对象:我'我已经创建了 MyLocationManager 来包装和隐藏 NSLocationManager,为什么我要公开一个 属性 只是为了测试它?
我发现一个非常简单的方法是 method swizzle NSLocationManager 的方法,所以我可以用模拟方法交换方法的实际实现,但是这看起来很不干净,我不知道它有多安全。
据我所知,不公开 属性 构造函数可能违反得墨忒耳定律,但另一方面,我认为 objective-c 这种模式具有一定的灵活性被接受了。
所以我的问题是,应该有什么方法我没有清楚地看到采用 property/constructor 注入,或者方法混合是一种常用的做法?
我应该更好地使用针对此场景采用的任何其他技术吗?
脚注:
这个问题即使对于包装网络代码和 类 的对象也是如此,比如 NSUrlSession.
好吧,在某一时刻,测试 set-up 可能比要测试的代码更复杂,所以人们可能还记得,测试是为了什么而发明的。
我认为一种实用的方法是,仅在包含单独的 class 延续的单独 header 中公开 属性。
经过长时间的测试驱动开发经验,我发现我的这个老问题很容易回答。
出于某种原因,我在想 属性 注入和依赖注入可以避免掩盖某些东西。
我根本不这么认为了。
在我原来问题的前一个场景中,现在我的正确答案是:
你必须公开 NSLocationManager 的依赖,也许提供一个构造注入器方法,和一个方便的构造方法,以使用 NSLocationManager 初始化位置管理器。
没有真正需要隐藏依赖项,即使它是一个包装器 class,因为在您发现自己需要调配某些方法的那一刻,您正在破解对象的 "internals"并在不测试界面的情况下对其进行调整,以不受控制的方式修改运行时行为。
如果你想调配,就调配,但这不是正确的选择。
自从我开始使用 TDD 以来,我一直坚信这是编写正确的模式兼容代码的好方法,而无需强制我的设计决策。 我发现在 80% 的情况下都是如此,但是在测试某些对象时遇到问题,由于某种原因,这些对象在实现中包装和隐藏了一个对象。
举个例子让我们考虑一个 MyLocationManager 对象,它为我要使用的对象提供一个通用接口,并包装在 NSLocationManager。 当我想测试这样的对象时,我当然必须提供一个模拟的 NSLocationManager。
我当然有 property/constructor 注入方法,但这意味着添加一个 属性 或构造函数参数,其中包含一个我只想对其他对象隐藏的对象:我'我已经创建了 MyLocationManager 来包装和隐藏 NSLocationManager,为什么我要公开一个 属性 只是为了测试它?
我发现一个非常简单的方法是 method swizzle NSLocationManager 的方法,所以我可以用模拟方法交换方法的实际实现,但是这看起来很不干净,我不知道它有多安全。
据我所知,不公开 属性 构造函数可能违反得墨忒耳定律,但另一方面,我认为 objective-c 这种模式具有一定的灵活性被接受了。
所以我的问题是,应该有什么方法我没有清楚地看到采用 property/constructor 注入,或者方法混合是一种常用的做法?
我应该更好地使用针对此场景采用的任何其他技术吗?
脚注: 这个问题即使对于包装网络代码和 类 的对象也是如此,比如 NSUrlSession.
好吧,在某一时刻,测试 set-up 可能比要测试的代码更复杂,所以人们可能还记得,测试是为了什么而发明的。
我认为一种实用的方法是,仅在包含单独的 class 延续的单独 header 中公开 属性。
经过长时间的测试驱动开发经验,我发现我的这个老问题很容易回答。 出于某种原因,我在想 属性 注入和依赖注入可以避免掩盖某些东西。 我根本不这么认为了。
在我原来问题的前一个场景中,现在我的正确答案是:
你必须公开 NSLocationManager 的依赖,也许提供一个构造注入器方法,和一个方便的构造方法,以使用 NSLocationManager 初始化位置管理器。
没有真正需要隐藏依赖项,即使它是一个包装器 class,因为在您发现自己需要调配某些方法的那一刻,您正在破解对象的 "internals"并在不测试界面的情况下对其进行调整,以不受控制的方式修改运行时行为。
如果你想调配,就调配,但这不是正确的选择。