gpt4 book ai didi

ios - OCMockito 验证和 NSError 的编译错误**

转载 作者:行者123 更新时间:2023-11-28 22:06:34 26 4
gpt4 key购买 nike

我无法编译这段代码:

[verify(mockedContext) deleteObject:item1];
[verify(mockedContext) deleteObject:item2];
[verify(mockedContext) save:anything()];<--compilation error for conversion id to NSError**

但是,在类似情况下,我可以使用具有附加语法的 given 宏通过编译:

    [[given([mockedContext save:nil]) withMatcher:anything()] willReturn:nil];

有什么可以帮助我通过验证的编译吗?

这里是编译错误:

Implicit conversion of an Objective-C pointer to 'NSError *__autoreleasing *' is disallowed with ARC

最佳答案

我假设“mockedContext”上的 save: 方法采用指向 NSError 的指针。

所以实际上,NSError 必须被视为save: 方法的额外返回值。这意味着您应该首先设定一个期望值。

我做了一个小例子:

我们从 Context 协议(protocol)开始,使用一个简单的方法接受 NSError**

@protocol Context <NSObject>
- (id)doWithError:(NSError *__autoreleasing *)err;
@end

接下来是一个使用此协议(protocol)的类,很像您的 SUT。我称它为 ContextUsingClass

@interface ContextUsingClass : NSObject

@property (nonatomic, strong) id<Context> context;
@property BOOL recordedError;

- (void)call;

@end

@implementation ContextUsingClass

- (void)call {
NSError *error;
[self.context doWithError:&error];
if (error) {
self.recordedError = YES;
}
}

@end

如您所见,当上下文方法 doWithError: 返回错误时,recordedError 属性设置为 YES。这是我们可以预期在我们的测试中是对还是错的东西。唯一的问题是,我们如何告诉 mock 导致错误(或成功而没有错误)?

答案相当简单,几乎是您问题的一部分:我们将 OCHamcrest 匹配器传递给 given 语句,这反过来会设置错误我们穿过一个街区。耐心等待,我们会到达那里。让我们首先编写拟合匹配器:

typedef void(^ErrorSettingBlock)(NSError **item);

@interface ErrorSettingBlockMatcher : HCBaseMatcher

@property (nonatomic, strong) ErrorSettingBlock errorSettingBlock;

@end


@implementation ErrorSettingBlockMatcher

- (BOOL)matches:(id)item {
if (self.errorSettingBlock) {
self.errorSettingBlock((NSError * __autoreleasing *)[item pointerValue]);
}
return YES;
}

@end

如果已设置此匹配器,它将调用 errorSettingBlock,并且将始终返回 YES,因为它接受所有项目。匹配器的唯一目的是在测试要求时设置错误。来自 OCMockito issue 22它是 fix ,我们了解到指向指针的指针被包装在 NSValue 对象中,所以我们应该打开它,并将其转换为我们众所周知的 NSError **

最后,测试结果如下:

@implementation StackOverFlowAnswersTests {
id<Context> context;
ContextUsingClass *sut;
ErrorSettingBlockMatcher *matcher;
}

- (void)setUp {
[super setUp];
context = mockProtocol(@protocol(Context));
sut = [[ContextUsingClass alloc] init];
sut.context = context;
matcher = [[ErrorSettingBlockMatcher alloc] init];
}

- (void)testContextResultsInError {
matcher.errorSettingBlock = ^(NSError **error) {
*error = [NSError errorWithDomain:@"dom" code:-100 userInfo:@{}];
};

[[given([context doWithError:nil]) withMatcher:matcher] willReturn:nil];
[sut call];
assertThatBool(sut.recordedError, is(equalToBool(YES)));
}

- (void)testContextResultsInSuccess {
[[given([context doWithError:nil]) withMatcher:matcher] willReturn:nil];
[sut call];
assertThatBool(sut.recordedError, is(equalToBool(NO)));
}

@end

结论

当您在 SUT 中调用通过指针到指针返回错误的方法时,您可能应该测试不同的可能结果,而不是仅仅验证该方法是否已被调用。

如果你的 SUT 忽略了这个错误,那么让你传递给匹配器的 block 保留一个 bool 标志来指示它是这样调用的:

- (void)testNotCaringAboutTheError {
__block BOOL called = NO;
matcher.errorSettingBlock = ^(NSError **error) {
called = YES;
};

[[given([context doWithError:nil]) withMatcher:matcher] willReturn:nil];
[sut call];
assertThatBool(called, is(equalToBool(YES)));
}

或者通过简单的验证:

- (void)testWithVerifyOnly {
[sut call];
[[verify(context) withMatcher:matcher] doWithError:nil];
}

PS:忽略错误可能是您不想做的事情...

关于ios - OCMockito 验证和 NSError 的编译错误**,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23808124/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com