You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

测试多代理回调方法时OCMVerify在mock回调执行后崩溃

崩溃根因
  • 主因:你在andDo的回调中从NSInvocation取出block参数时,没有手动执行copy操作。block作为方法参数传递时默认存储在栈区,NSInvocation不会自动对block类型参数做内存管理,你拿到的指针指向的栈内存在fetchInt:方法返回后就会被回收,此时再调用block就会触发EXEC_BAD_ACCESS野指针崩溃。
  • 次因:检查你的测试代码中_mockedDelegate是否已正确初始化,若为未初始化的野指针,后续调用delegateDoStuff方法时也会触发相同崩溃。
修复方案

在从NSInvocation读取block后立刻调用copy方法,将栈block复制到堆上,保证调用时内存有效。修复后的测试代码如下:

- (void) testWithMultipleCallbacks {
    // 若之前未初始化_mockedDelegate,需补充初始化逻辑
    if (!_mockedDelegate) {
        _mockedDelegate = OCMProtocolMock(@protocol(MyDelegate));
    }

    id <MyDelegateWithCallback> mockDelegateWithCallback = OCMProtocolMock(@protocol(MyDelegateWithCallback));
    OCMStub([mockDelegateWithCallback fetchInt:[OCMArg any]]).andDo(^(NSInvocation *invocation) {
      void (^block)(int) = NULL;
      [invocation getArgument:&block atIndex:2];
      // 新增copy操作,将栈block转移到堆内存
      block = [block copy];
      NSLog(@"got here"); 
      block(33); 
    });
    [_classUnderTest methodWithMultipleCallbacks: _mockedDelegate withSecondDelegate: mockDelegateWithCallback];
    // 可直接校验参数为32,提升测试准确性
    OCMVerify(OCMTimes(1), [_mockedDelegate delegateDoStuff:32]);
}
额外优化建议

如果你的业务代码中fetchInt:是异步执行回调的场景,还需要在业务代码中将传入的callback block copy到堆上,避免业务代码运行时出现同样的野指针问题。

内容的提问来源于stack exchange,提问作者hao chen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 23:27:03