模拟 CKContainer 进行单元测试
Mocking CKContainer for Unit Testing
我在我的应用程序中使用 CloudKit 并试图模拟 CKContainer 来测试我的管理器。这是我尝试过的:
func testAccountStatus() {
class MockCloudContainer: CKContainer {
override func accountStatusWithCompletionHandler(completionHandler: ((CKAccountStatus, NSError!) -> Void)!)
{
completionHandler(CKAccountStatus.NoAccount, NSError())
}
}
let loginManager = LoginManager.sharedInstance
let expectation = expectationWithDescription("iCloudStatus")
var isTestFinished = false
loginManager.iCloudStatusWithCompletionHandler { (status, error) -> Void in
if (isTestFinished) {
return
}
expectation.fulfill()
XCTAssertTrue(status.isEqualToString("NoAccount"), "Status is Available")
}
waitForExpectationsWithTimeout(5, { error in
isTestFinished = true
XCTAssertNil(error, "Error")
})
但是我在编译代码时遇到错误
:0: error: cannot override 'init' which has been marked unavailable
我使用模拟对象测试我的 LoginManager class 的最佳方式是什么?
谢谢
目前无法模拟 CKContainer。唯一的解决方案是在您的应用程序和 CloudKit 代码之间创建一个薄数据访问层,然后模拟该层。但是您仍然无法对薄层本身进行单元测试。
这个问题我有个想法。但是我不擅长 swift 所以我在 Objective-C
中提供了我的代码
首先,尝试在您的 testClass 中创建 CKContainerMock
,如下所示:
@interface CKContainerMock : CKContainer
@property (nonatomic, copy) void (^mCompletionHandlerMock)(CKAccountStatus accountStatus,NSError *error);
- (void)accountStatusWithCompletionHandler:(void (^)(CKAccountStatus accountStatus, NSError *error))completionHandler
@end
@implementation CKContainerMock
- (void)accountStatusWithCompletionHandler:(void (^)(CKAccountStatus accountStatus, NSError *error))completionHandler {
self.mCompletionHandlerMock = completionHandler;
}
@end
在你的测试函数中
示例:
成功案例:
-(void) testCKContainerResultSucces {
LoginManager loginManager = [LoginManager sharedInstance];
CKContainerMock *ckContainerMock = [[CKContainerMock alloc] init];
[loginManager setCKContainer:ckContainerMock]; // Change your ckContainer object to mockObject.
[loginManager iCloudStatusWithCompletionHandler:^(CKAccountStatus accountStatus,NSError *error) {
XCAssert(accountStatus == CKAccountStatusAvailable);
}];
loginManager.ckContainer.mCompletionHandlerMock(CKAccountStatusAvailable,nil);
}
错误案例:
-(void) testCKContainerResultError {
LoginManager loginManager = [LoginManager sharedInstance];
CKContainerMock *ckContainerMock = [[CKContainerMock alloc] init];
[loginManager setCKContainer:ckContainerMock]; //Change your ckContainer object to mockObject.
[loginManager iCloudStatusWithCompletionHandler:^(CKAccountStatus accountStatus,NSError *error) {
XCAssertNotNil(error);
}];
loginManager.ckContainer.mCompletionHandlerMock(nil,[NSError errorWithDomain:NSPOSIXErrorDomain code:22 userInfo:nil]);
}
希望对您有所帮助。
我在我的应用程序中使用 CloudKit 并试图模拟 CKContainer 来测试我的管理器。这是我尝试过的:
func testAccountStatus() {
class MockCloudContainer: CKContainer {
override func accountStatusWithCompletionHandler(completionHandler: ((CKAccountStatus, NSError!) -> Void)!)
{
completionHandler(CKAccountStatus.NoAccount, NSError())
}
}
let loginManager = LoginManager.sharedInstance
let expectation = expectationWithDescription("iCloudStatus")
var isTestFinished = false
loginManager.iCloudStatusWithCompletionHandler { (status, error) -> Void in
if (isTestFinished) {
return
}
expectation.fulfill()
XCTAssertTrue(status.isEqualToString("NoAccount"), "Status is Available")
}
waitForExpectationsWithTimeout(5, { error in
isTestFinished = true
XCTAssertNil(error, "Error")
})
但是我在编译代码时遇到错误
:0: error: cannot override 'init' which has been marked unavailable
我使用模拟对象测试我的 LoginManager class 的最佳方式是什么?
谢谢
目前无法模拟 CKContainer。唯一的解决方案是在您的应用程序和 CloudKit 代码之间创建一个薄数据访问层,然后模拟该层。但是您仍然无法对薄层本身进行单元测试。
这个问题我有个想法。但是我不擅长 swift 所以我在 Objective-C
中提供了我的代码
首先,尝试在您的 testClass 中创建 CKContainerMock
,如下所示:
@interface CKContainerMock : CKContainer
@property (nonatomic, copy) void (^mCompletionHandlerMock)(CKAccountStatus accountStatus,NSError *error);
- (void)accountStatusWithCompletionHandler:(void (^)(CKAccountStatus accountStatus, NSError *error))completionHandler
@end
@implementation CKContainerMock
- (void)accountStatusWithCompletionHandler:(void (^)(CKAccountStatus accountStatus, NSError *error))completionHandler {
self.mCompletionHandlerMock = completionHandler;
}
@end
在你的测试函数中
示例:
成功案例:
-(void) testCKContainerResultSucces {
LoginManager loginManager = [LoginManager sharedInstance];
CKContainerMock *ckContainerMock = [[CKContainerMock alloc] init];
[loginManager setCKContainer:ckContainerMock]; // Change your ckContainer object to mockObject.
[loginManager iCloudStatusWithCompletionHandler:^(CKAccountStatus accountStatus,NSError *error) {
XCAssert(accountStatus == CKAccountStatusAvailable);
}];
loginManager.ckContainer.mCompletionHandlerMock(CKAccountStatusAvailable,nil);
}
错误案例:
-(void) testCKContainerResultError {
LoginManager loginManager = [LoginManager sharedInstance];
CKContainerMock *ckContainerMock = [[CKContainerMock alloc] init];
[loginManager setCKContainer:ckContainerMock]; //Change your ckContainer object to mockObject.
[loginManager iCloudStatusWithCompletionHandler:^(CKAccountStatus accountStatus,NSError *error) {
XCAssertNotNil(error);
}];
loginManager.ckContainer.mCompletionHandlerMock(nil,[NSError errorWithDomain:NSPOSIXErrorDomain code:22 userInfo:nil]);
}
希望对您有所帮助。