通过 OCMock 存根覆盖方法
Posted
技术标签:
【中文标题】通过 OCMock 存根覆盖方法【英文标题】:overwriting a method via stubbing with OCMock 【发布时间】:2012-08-20 19:23:04 【问题描述】:我正在尝试测试一个计时器对象在关卡完成后是否停止。我有以下代码:
-(void)advanceLevel
int nextLevelId = self.currentLevel.id + 1;
self.currentLevel = [[Level alloc] initWithIdentifier:nextLevelId];
[self.timer stop];
[self prepareLevel];
...
prepareLevel 方法重置计时器值并在其上调用“start”--- 所以为了测试advanceLevel 实际停止计时器,我需要覆盖prepareLevel 方法。
所以在我的单元测试中,我做了以下事情:
-(void)testItStopsTheTimer
[timer start];
id mockGame = [OCMockObject partialMockForObject:game];
[[[mockGame stub] andReturn:nil] prepareLevel];
[game advanceLevel];
STAssertFalse(timer.active, nil);
这导致 XCode 说“testItStopsTheTimer (Gametests) failed. Ended up in subclass forwarder for Game-0x12383060.......”
那么,是不是不能把现有的方法存根,然后用虚无代替呢?
【问题讨论】:
【参考方案1】:OCMock 绝对可以实现您想要做的事情。
prepareLevel
的方法签名是什么?如果它返回 void,您的模拟设置应该是:
[[mockGame stub] prepareLevel];
不是:
[[[mockGame stub] andReturn:nil] prepareLevel];
【讨论】:
【参考方案2】:OCMock 可以实现您想要做的事情。在您的测试代码中,有一行突出:
id mockGame = [OCMockObject partialMockForObject:game];
问题是,“游戏”从何而来?是否在多个测试中使用了相同的实例?您看到的错误可能是由以下顺序引起的:您在部分模拟上使用了期望,调用了预期的方法,然后再次调用了该方法,但是现在没有期望了,部分模拟也不知道该怎么办。
更新:我刚刚更改了 OCMock,以便在这种情况下,模拟只是将方法转发给真实对象。见:https://github.com/erikdoe/ocmock/commit/e03d4fe74465b4fe3fa33552e036de8986f8dec2
【讨论】:
如果我将 arg 传递给与运行测试时传入的 arg 不匹配的期望方法,我仍然会收到此错误。如果我将正确的 arg 传递给 expect 方法,测试就可以通过了吗?由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“在 KIViewController-0x12c17740-380651950.550829 的子类转发器中结束,带有未存根的方法操作操作DidFinishWithError:”以上是关于通过 OCMock 存根覆盖方法的主要内容,如果未能解决你的问题,请参考以下文章
OCMock: OCMPartialMock 对象调用实际方法而不是存根