在 Objective-C++ 中,为了进行测试,如何在运行时使类为 nil?



情况是这样的:

在异步函数中,我捕获了一个弱自我。

__block auto weakSelf = self;

然后,在街区内,我捕捉到了一个强大的自我。

[_someIvar someAsyncMethod:^{
__strong auto strongSelf = weakSelf;
}];

但是,如果strongSelf为零,我会做一些错误处理和报告。

if (!strongSelf) {
_NotifyDelegate(someDeallocationError); // C
}

整件事:

__block auto weakSelf = self;
[_someIvar someAsyncMethod:^{
__strong auto strongSelf = weakSelf;
if (!strongSelf) {
// How can I trigger this line?
_NotifyDelegate(someDeallocationError); // C
}
}
}];

这都是遗留代码,我正在使用 OCMock 添加单元测试。如何在运行时使 strongSelf nil 并触发该委托通知?

据我所知,您尚未指定任何类名,但假设您有:

@interface SomeClass
…
@end
…
@interface IvarClass
- (void) someAsyncMethod:(void(^)(void))block;
@end
…
@implementation SomeClass
{
IvarClass* _someIvar;
}
…
- (void)someMethod
{
__block auto weakSelf = self;
[_someIvar someAsyncMethod:^{
__strong auto strongSelf = weakSelf;
if (!strongSelf) {
// How can I trigger this line?
_NotifyDelegate(someDeallocationError); // C
}
}];
}
@end

在这种情况下,我会用一个StubIvarClassDelayedAsyncIvarClass进行子类化,您可以在其中覆盖- (void) someAsyncMethod:以便块简单地存储在 ivar 中。然后,沿着调用块的- (void)completeAsyncMethod行在其上实现另一个方法。

您需要使用此StubIvarClassDelayedAsync的实例作为测试中的_someIvar- 或者您可以通过SomeClass上的现有 API 直接注入它,否则您可能需要子类化SomeClass以更改创建生产实例的位置。

在测试方法中将它们放在一起:在@autoreleasepool块中,创建SomeClass(或其存根子类)的实例,使用StubIvarClassDelayedAsync的实例准备它,然后调用someMethod。这反过来应该会导致调用someAsyncMethod:的覆盖版本,该版本存储块引用。(您可以断言调用该方法是为了良好的度量。 在测试中nilSomeClass指针,并关闭池块以删除任何最后的引用。你可能想断言dealloc在你的SomeClass instance上被调用,如果使用虚拟子类,你可以很容易地做到这一点。但是,请确保保留指向StubIvarClassDelayedAsync实例的指针。最后,在该存根实例上调用completeAsyncMethod,这应该会导致块采用错误处理分支。

如果您提供的不仅仅是未命名的片段,我会更具体地介绍代码示例,如果您在各自的方法中在这些片段之前或之后有代码,那么可能需要首先考虑或重构。实名制也很有用。

相关内容

最新更新