Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/23.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
Objective c 如何使用OCMock部分模拟遗留代码中的对象?_Objective C_Mocking_Ocmock - Fatal编程技术网

Objective c 如何使用OCMock部分模拟遗留代码中的对象?

Objective c 如何使用OCMock部分模拟遗留代码中的对象?,objective-c,mocking,ocmock,Objective C,Mocking,Ocmock,我想完成所描述的工作,即在遗留代码中创建模拟。然而,我需要的不是漂亮的嘲弄 例如,考虑排行榜的行为完全类似于除了实现一个被破坏的版本 LooStasksFuleTythHunter:> 我在一个XCTestCase中尝试了这段代码,但在运行时,它在指示行中失败了:ocminoviationmatcher引发了一个EXC\u BAD\u ACCESS错误。也许有一些无限递归正在进行 id leaderboardMock = OCMClassMock(GKLeaderboard.class); O

我想完成所描述的工作,即在遗留代码中创建模拟。然而,我需要的不是漂亮的嘲弄

例如,考虑排行榜的行为完全类似于除了实现一个被破坏的版本 LooStasksFuleTythHunter:>

我在一个
XCTestCase
中尝试了这段代码,但在运行时,它在指示行中失败了:
ocminoviationmatcher
引发了一个
EXC\u BAD\u ACCESS
错误。也许有一些无限递归正在进行

id leaderboardMock = OCMClassMock(GKLeaderboard.class);
OCMStub([leaderboardMock alloc])
    .andReturn(OCMPartialMock([GKLeaderboard alloc]));
OCMStub([leaderboardMock loadScoresWithCompletionHandler: [OCMArg any]])
    .andDo(^(NSInvocation *invocation) { /* ... */ });

// these parts normally nested inside legacy code

GKLeaderboard *leaderboard = /* raises EXC_BAD_ACCESS */
    [[GKLeaderboard alloc] initWithPlayers: @[ GKLocalPlayer.localPlayer ]];
leaderboard.identifier = @"Test";

[leaderboard loadScoresWithCompletionHandler: nil /* ... */ ];
我做错了什么?对于部分实体模型,这可能吗

更新我现在可以看到指示的行可能(非常明显)导致无限递归,但还不知道如何避免(或中断)它


更新我也没有成功地尝试引入一个专门的课程,包括
OCMStub([leadboardmock alloc])。andReturn([leadboardmock alloc])
(也不包括
OCMStub([leadboardmock initWithPlayers:[OCMArg any]])。andReturn([leadboardmock alloc]initWithPlayers:nil])
)。也许,
OCMock
init
级别上发挥了神奇的作用(上面说:“不可能存根
init
方法,因为它是由mock本身实现的”),因此这种尝试将
alloc
级别(或者
initWithPlayers:
)无法达到预期效果。

我不确定是否遵循了您的意图。这似乎是个误会。以下内容对您不适用吗

GKLeaderboard *leaderboard = [[GKLeaderboard alloc] initWithPlayers: ... ];
id leaderboardMock = OCMPartialMock(leaderboard);
OCMStub([leaderboarMock loadScoresWithCompletionHandler: ...]);
可以不受限制地使用法线对象。您可以使用为对象创建的部分模拟来操纵
排行榜中的实际实例。这就是部分嘲弄的美妙之处

更新:如果对象创建不在您的控制之下,您可以尝试以下操作:

GKLeaderboard *leaderboard = [[GKLeaderboard alloc] initWithPlayers: ... ];
id leaderboardMock = OCMPartialMock(leaderboard);

OCMStub([leaderboardMock alloc]).andReturn(leaderboardMock);
OCMStub([leaderboardMock initWithPlayers:[OCMArg any]).andReturn(leaderboard);

OCMStub([leaderboarMock loadScoresWithCompletionHandler: ...]);

我现在已经得出结论,这将是一个可能的选择


例如,替换方法可以从遗留代码的上下文中生成部分模拟,从而在该上下文中引入部分模拟,而无需更改遗留API。

您不应该使用以下行,它将模拟整个类,并且不会调用任何真实对象


OCMClassMock(gkleadboard.class)

问题(正如我现在所看到的)是,排行榜是在遗留代码中创建的,我无法触及。因此,我无法调用
id leadboardmock=OCMPartialMock(排行榜)在其创建和使用之间(可以说是在第一行和第三行代码之间)。另请参见。您不能模拟
init
方法,但是
initWithPlayers:
应该可以工作。因此,也许可以尝试模拟alloc/init。对于调用
OCMPartialMock
(与
OCMClassMock
)您需要知道排行榜的实例。不幸的是,它只有在遗留代码库中创建之后才为人所知,并且没有被某些API公开……顺便说一句,模仿
initWithPlayers:
对我也不起作用(如Q中所述)。Thx对于您的努力,但这种方法不合适。(我以前试过)。您会将哪些玩家(
)传入“早期”以匹配遗留代码选择的“晚期”?我认为,必须有一种方法来配置模拟的
alloc
s或
init
s,以便它们返回新的模拟实例(而不仅仅是单个实例或预分配的实例,可能来自池)。