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
例如,考虑排行榜的行为完全类似于除了实现一个被破坏的版本
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,以便它们返回新的模拟实例(而不仅仅是单个实例或预分配的实例,可能来自池)。