Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/113.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 为什么在objective-c中使用DI进行模拟比模拟对象更好?_Ios_Objective C_Unit Testing_Dependency Injection_Mocking - Fatal编程技术网

Ios 为什么在objective-c中使用DI进行模拟比模拟对象更好?

Ios 为什么在objective-c中使用DI进行模拟比模拟对象更好?,ios,objective-c,unit-testing,dependency-injection,mocking,Ios,Objective C,Unit Testing,Dependency Injection,Mocking,这说明: 虽然有时有一些不使用DI模拟对象的合理方法 (通常通过模拟类方法,如OCMock示例所示 上面),这通常是完全不可能的。即使可能,, 测试设置的复杂性可能超过其好处。如果 如果您一直使用依赖注入,您会发现 使用存根和模拟的测试会容易得多 但这并不能解释为什么。DI(注入符合协议的id对象)在Objective-C中比简单的OCMockito更适合模拟的可能场景有哪些: [given([mockArray objectAtIndex:0]) willReturn:@"first"];

这说明:

虽然有时有一些不使用DI模拟对象的合理方法 (通常通过模拟类方法,如OCMock示例所示 上面),这通常是完全不可能的。即使可能,, 测试设置的复杂性可能超过其好处。如果 如果您一直使用依赖注入,您会发现 使用存根和模拟的测试会容易得多

但这并不能解释为什么。DI(注入符合协议的
id
对象)在Objective-C中比简单的OCMockito更适合模拟的可能场景有哪些:

[given([mockArray objectAtIndex:0]) willReturn:@"first"];
 [verifyCount(mockArray, times(1)) objectAtIndex:];

假设您正在尝试测试对象与其子对象之一交互的更复杂行为。要确保父对象正确运行,必须模拟子对象的所有方法,甚至可能跟踪其不断变化的状态


但如果你这样做了,你只是以一种混乱而复杂的方式写了一个全新的对象。编写一个全新的对象并告诉父对象使用它会更简单。

使用DI,您可以在运行时注入模型,它不绑定在类中,而只绑定在配置中。
当您想要模拟时,只需创建一个模拟模型并注入该模型,而不是实际数据。除了模型之外,您在一行中更改了实现

请参阅,以获取实际操作示例或其背后的想法


免责声明:当然,你可以模仿模型以外的其他东西,但这可能是最常见的用例。

答案是:这并不更好。如果你需要一些超级定制的行为,那就更好了

最好的一点是,您不必为注入的每个类创建接口/协议,您可以将真正需要注入的模块限制为DI,从而使代码更干净、更雅格尼


它适用于任何动态语言,或带有反射的语言。仅仅为了单元测试而创建如此多的混乱让我觉得是个坏主意。

我注意到,当原始类执行一些异步操作时,为测试目标创建一个单独的类更容易

假设您为UIViewController编写了一个测试,该测试具有LoginSystem依赖项,该依赖项使用AFNetworking向API发出请求。LoginSystem将块参数作为回调。(UIViewController->LoginSystem->AFNetworking)

如果您对LoginSystem进行模拟,您可能会遇到如何在成功/失败时启动回调块以测试UIViewController行为的问题。当我尝试这样做时,我以检索块参数结束,然后我必须在测试文件中调用它

另一方面,如果您为LoginSystem创建一个单独的类(让我们称之为LoginSystemStub,它从LoginSystem扩展而来),那么您可以在3行代码中和测试文件之外“模拟”一个行为。我们还应该保持测试文件的干净和可读性

另一种情况是verify()不能用于检查异步行为。调用expect(smth2)要容易得多。.equal(smth)

编辑:


指向NSError(NSError**)的指针也不能与verify()一起很好地工作,最好创建一个存根:D

您是否暗示对每个依赖项使用DI,然后创建一个单独的模拟类,比OCMockito存根更干净/更不复杂?我不这么认为。在大多数情况下,跟踪模拟的变化状态似乎毫无意义。你唯一需要从模拟中得到的是它返回一些数据,并找出是否调用了某些方法。是的,我知道如何使用注入模拟类进行模拟。我只是想知道使用real类是否如博客中所说的那样优越,如果是,原因是什么?谢谢:)所以我认为它适合我的状态网“如果你需要一些超级定制的行为,这才更好。”