IOS VIPER:协议如何帮助单元测试?
IOS VIPER: How protocol helps in Unit Testing?
我对 VIPER 体系结构中协议的好处有点困惑。
我了解 DI(依赖注入)是通过协议实现的,有助于避免对象之间的直接依赖 - 我同意。
但我正在从使用的角度来看一个真正的好处,一个例子可能是 - 特别是协议如何帮助在单元测试中受益(测试交互器部分)。
我们不能通过方法回调的 using 块实现同样的功能吗?
希望有人能通过一些例子帮助我从使用的角度理解
干杯
通过使用协议,您可以更轻松地换出 VIPER 结构中的实现。例如,您可能有一个正在使用正在写入文件系统的 class 的交互器。您不想在单元测试中测试文件系统,所以如果您将文件系统写操作放在交互器中的协议后面,您就可以用内存中的实现替换文件系统写操作。
至于交互器本身的协议,我认为在您的选择上更加务实一点是值得的。如果为测试构建交互器很容易,并且作为测试的一部分不会引起任何副作用,那么可能就不需要协议了。另一方面,如果您必须创建许多其他依赖项,那么让交互器符合协议可能是值得的,这样您就可以更轻松地伪造从交互器获得的输出。
使用回调,例如从 Interactor 到 Presenter,会使测试 Presenter 变得更加困难。
在为 Presenter 如何处理输入(从 Interactor 发送)编写测试时,您的测试必须在 Presenter 上调用一些方法,这将导致 Presenter 对 Interactor 进行调用,这将导致 Interactor向 Presenter 发送数据。
通过让 Presenter 实现由 Interactor 定义的协议,您的测试可以直接调用 Presenter 上的适当输入法。
就声明协议而言,我以模拟角色而非对象的方式实践 TDD (http://www.jmock.org/oopsla2004.pdf)。这些协议通过关注对象做什么(它的角色)而不是它如何做来帮助提供更好的抽象。
协议本身对单元测试没有多大价值。您的单元测试将为被测系统的依赖项提供测试替身 (http://martinfowler.com/bliki/TestDouble.html)。即使您将依赖项公开为具体的 classes,您仍然可以为您的测试创建测试替身。
在 Objective-C 中,您可以使用模拟库,例如 OCMock (http://ocmock.org), or OCMockito (https://github.com/jonreid/OCMockito),来创建具体的存根、间谍或模拟 class。
在 Swift 中,您可以通过子class 将每个用作依赖项的具体 classes 创建测试替身。
简而言之,协议不是用来简化单元测试的,而是用来在更高的抽象层次上描述应用程序的作用。
这是一个例子,说明抽象协议在事后是如何有益的:
我创建了一个协议来表示用户可以在屏幕上执行的操作,例如ProfileUserActions
,具有 changeName
和 changeAddress
等操作。 Presenter 实现了 ProfileUserActions
,而 View 接受了 ProfileUserActions
作为依赖项。当用户点击屏幕上的按钮时,视图会向其 userActions
对象发送适当的消息。
当我想添加分析时,我能够创建一个新的、独立的 ProfileAnalytics
class,它也实现了 ProfileUserActions
。我在 View 和 Presenter 之间插入了分析对象,这允许应用程序捕获分析,而无需修改 View 或 Presenter。
我对 VIPER 体系结构中协议的好处有点困惑。 我了解 DI(依赖注入)是通过协议实现的,有助于避免对象之间的直接依赖 - 我同意。
但我正在从使用的角度来看一个真正的好处,一个例子可能是 - 特别是协议如何帮助在单元测试中受益(测试交互器部分)。
我们不能通过方法回调的 using 块实现同样的功能吗? 希望有人能通过一些例子帮助我从使用的角度理解
干杯
通过使用协议,您可以更轻松地换出 VIPER 结构中的实现。例如,您可能有一个正在使用正在写入文件系统的 class 的交互器。您不想在单元测试中测试文件系统,所以如果您将文件系统写操作放在交互器中的协议后面,您就可以用内存中的实现替换文件系统写操作。
至于交互器本身的协议,我认为在您的选择上更加务实一点是值得的。如果为测试构建交互器很容易,并且作为测试的一部分不会引起任何副作用,那么可能就不需要协议了。另一方面,如果您必须创建许多其他依赖项,那么让交互器符合协议可能是值得的,这样您就可以更轻松地伪造从交互器获得的输出。
使用回调,例如从 Interactor 到 Presenter,会使测试 Presenter 变得更加困难。
在为 Presenter 如何处理输入(从 Interactor 发送)编写测试时,您的测试必须在 Presenter 上调用一些方法,这将导致 Presenter 对 Interactor 进行调用,这将导致 Interactor向 Presenter 发送数据。
通过让 Presenter 实现由 Interactor 定义的协议,您的测试可以直接调用 Presenter 上的适当输入法。
就声明协议而言,我以模拟角色而非对象的方式实践 TDD (http://www.jmock.org/oopsla2004.pdf)。这些协议通过关注对象做什么(它的角色)而不是它如何做来帮助提供更好的抽象。
协议本身对单元测试没有多大价值。您的单元测试将为被测系统的依赖项提供测试替身 (http://martinfowler.com/bliki/TestDouble.html)。即使您将依赖项公开为具体的 classes,您仍然可以为您的测试创建测试替身。
在 Objective-C 中,您可以使用模拟库,例如 OCMock (http://ocmock.org), or OCMockito (https://github.com/jonreid/OCMockito),来创建具体的存根、间谍或模拟 class。
在 Swift 中,您可以通过子class 将每个用作依赖项的具体 classes 创建测试替身。
简而言之,协议不是用来简化单元测试的,而是用来在更高的抽象层次上描述应用程序的作用。
这是一个例子,说明抽象协议在事后是如何有益的:
我创建了一个协议来表示用户可以在屏幕上执行的操作,例如ProfileUserActions
,具有 changeName
和 changeAddress
等操作。 Presenter 实现了 ProfileUserActions
,而 View 接受了 ProfileUserActions
作为依赖项。当用户点击屏幕上的按钮时,视图会向其 userActions
对象发送适当的消息。
当我想添加分析时,我能够创建一个新的、独立的 ProfileAnalytics
class,它也实现了 ProfileUserActions
。我在 View 和 Presenter 之间插入了分析对象,这允许应用程序捕获分析,而无需修改 View 或 Presenter。