OCMock: how to stub -[NSString stringWithContentsOfURL:encoding:error:]
OCMock: how to stub -[NSString stringWithContentsOfURL:encoding:error:]
我已经尝试了很多东西。这仍然不起作用:
id stringMock = OCMClassMock([NSString class]);
[[[[stringMock stub] ignoringNonObjectArgs] stringWithContentsOfURL:[OCMArg anyPointer] encoding:NSUTF8StringEncoding error:(NSError * __autoreleasing *)[OCMArg anyPointer]] andReturn:stringFromFile];
如何在我的代码中的任何地方制作 -[NSString stringWithContentsOfURL:encoding:error:] return stringFromFile
?
很遗憾,这是不可能的。
来自 OCMock documentation 关于限制(第 10 节):
10.5 Class methods on NSString cannot be stubbed or verified
id stringMock
= OCMClassMock([NSString class]); // the following will not work OCMStub([stringMock stringWithContentsOfFile:[OCMArg any]
encoding:NSUTF8StringEncoding error:[OCMArg setTo:nil]]);
It is not
possible to stub or verify class methods on NSString. Trying to do so
has no effect.
但是,您可以包装 NSString
并模拟包装器。这意味着您需要用这个包装器替换代码中的所有调用,但测试会起作用..
举个例子:
包装器:
@interface NSStringWrapper : NSObject
+ (nullable id)stringWithContentsOfURL:(NSURL *)url;
@end
@implementation NSStringWrapper
+ (nullable id)stringWithContentsOfURL:(NSURL *)url
{
return [NSString stringWithContentsOfURL:url];
}
@end
测试:
static NSString *stringFromFile = @"myStringFromFile";
-(void)testStringWrapper
{
id nsstringWrapperMock = OCMClassMock([NSStringWrapper class]);
OCMStub(ClassMethod([nsstringWrapperMock stringWithContentsOfURL:OCMOCK_ANY])).andDo(^(NSInvocation *invocation)
{
[invocation setReturnValue:&stringFromFile];
});
NSURL *fakeURL = [NSURL URLWithString:@"htttp://google.com"];
NSString *test = [NSStringWrapper stringWithContentsOfURL:fakeURL];
XCTAssertEqual(test, stringFromFile, @"Should always return stringFromFile");
}
另一种选择是尝试 OCMockito,它以不同于 OCMock 的方式模拟 class 方法。
__strong Class mockStringClass = mockClass([NSString class]);
[[given([mockStringClass stringWithContentsOfFile:anything()
encoding:NSUTF8StringEncoding
error:NULL])
withMatcher:anything() forArgument:2]
willReturn:stringFromFile];
与 swizzles class 方法的 OCMock 不同,这需要您注入 class。也就是说,不是生产代码直接调用
str = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL];
你需要做类似
的事情
str = [self.stringClass stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL];
您应该能够添加 OCMockito 而不会中断您现有的 OCMock 使用。
我已经尝试了很多东西。这仍然不起作用:
id stringMock = OCMClassMock([NSString class]);
[[[[stringMock stub] ignoringNonObjectArgs] stringWithContentsOfURL:[OCMArg anyPointer] encoding:NSUTF8StringEncoding error:(NSError * __autoreleasing *)[OCMArg anyPointer]] andReturn:stringFromFile];
如何在我的代码中的任何地方制作 -[NSString stringWithContentsOfURL:encoding:error:] return stringFromFile
?
很遗憾,这是不可能的。
来自 OCMock documentation 关于限制(第 10 节):
10.5 Class methods on NSString cannot be stubbed or verified
id stringMock = OCMClassMock([NSString class]); // the following will not work OCMStub([stringMock stringWithContentsOfFile:[OCMArg any] encoding:NSUTF8StringEncoding error:[OCMArg setTo:nil]]);
It is not possible to stub or verify class methods on NSString. Trying to do so has no effect.
但是,您可以包装 NSString
并模拟包装器。这意味着您需要用这个包装器替换代码中的所有调用,但测试会起作用..
举个例子:
包装器:
@interface NSStringWrapper : NSObject
+ (nullable id)stringWithContentsOfURL:(NSURL *)url;
@end
@implementation NSStringWrapper
+ (nullable id)stringWithContentsOfURL:(NSURL *)url
{
return [NSString stringWithContentsOfURL:url];
}
@end
测试:
static NSString *stringFromFile = @"myStringFromFile";
-(void)testStringWrapper
{
id nsstringWrapperMock = OCMClassMock([NSStringWrapper class]);
OCMStub(ClassMethod([nsstringWrapperMock stringWithContentsOfURL:OCMOCK_ANY])).andDo(^(NSInvocation *invocation)
{
[invocation setReturnValue:&stringFromFile];
});
NSURL *fakeURL = [NSURL URLWithString:@"htttp://google.com"];
NSString *test = [NSStringWrapper stringWithContentsOfURL:fakeURL];
XCTAssertEqual(test, stringFromFile, @"Should always return stringFromFile");
}
另一种选择是尝试 OCMockito,它以不同于 OCMock 的方式模拟 class 方法。
__strong Class mockStringClass = mockClass([NSString class]);
[[given([mockStringClass stringWithContentsOfFile:anything()
encoding:NSUTF8StringEncoding
error:NULL])
withMatcher:anything() forArgument:2]
willReturn:stringFromFile];
与 swizzles class 方法的 OCMock 不同,这需要您注入 class。也就是说,不是生产代码直接调用
str = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL];
你需要做类似
的事情str = [self.stringClass stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL];
您应该能够添加 OCMockito 而不会中断您现有的 OCMock 使用。