使用Xcode 6和OCMockito测试块



我开始使用objective-c进行单元测试,我需要知道如何使用OCMockito和Xcode 6测试块。

我正在测试一个交互程序,这个交互程序应该返回一个数组作为块参数,我必须向Provider文件询问元素。

这是我想要测试的方法:

    - (void)userPoiListsWithSuccessBlock:(MNBSavePoisInteractorSuccess)success {
        self.poiListEntityArray = [self.poiListProvider poiListsForUser:self.loggedUser];
        self.poiListViewObjectArray = [self viewPoiListObjectListWithPoiLists:self.poiListEntityArray];
        success(self.poiListViewObjectArray);
    }

首先,我设置了要使用的元素

    self.mockPoiListProvider = mock([PoiListProvider class]);
    self.sut = [[MNBSavePoisInteractor alloc] initWithManagedObjectContext:self.coreDataStack.managedObjectContext andPoiListProvider:self.mockPoiListProvider];
- (UserEntity *)loggedUserMock {
    UserEntity *mockLoggedUser = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([UserEntity class]) inManagedObjectContext:self.coreDataStack.managedObjectContext];
    mockLoggedUser.userId=@"1";
    mockLoggedUser.username=@"user";
    mockLoggedUser.loggedUser=@YES;
    return mockLoggedUser;
}
- (InMemoryCoreDataStack *)coreDataStack{
    if (!_coreDataStack) {
        _coreDataStack = [[InMemoryCoreDataStack alloc] init];
    }
    return _coreDataStack;
}
- (PoiListEntity *)poiListFake {
    PoiListEntity *fake = [NSEntityDescription insertNewObjectForEntityForName:@"PoiListEntity" inManagedObjectContext:self.coreDataStack.managedObjectContext];
    fake.name = @"Test";
    fake.poisCount = @2;
   [fake addContributorsObject:[self loggedUserMock]];
    return fake;
}

然后,我做测试。我使用Xcode 6 waitForExpectation来管理异步方法。我想我做错了什么。

- (void)waitForExpectation {
    [self waitForExpectationsWithTimeout:5.0 handler:^(NSError *error) {
        if (error) {
            NSLog(@"Timeout Error: %@", error);
        }
    }];
}
- (void)testShouldReturnPoiLists {
    XCTestExpectation *expectation =  [self expectationWithDescription:@"Waiting method ends"];
    [given([self.mockPoiListProvider poiListsForUser:[self loggedUserMock]]) willReturn:@[[self poiListFake]]];
    [self.sut userPoiListsWithSuccessBlock:^(NSArray *results) {
        [expectation fulfill];
           XCTAssert(resutls.count == 1, @"Results %zd", resutls.count);
    }];
    [self waitForExpectation];
}

我知道,如果我在给定方法中的willReturn中给定对象,当我调用我想要测试的sut方法时,它应该返回我之前给出的内容。这是真的吗?感谢

我没有看到异步代码。您只需要一个捕获结果的块,所以使用__block变量使结果在块之外可用。然后你可以断言你想要的任何东西:

- (void)testShouldReturnPoiLists {
    [given([self.mockPoiListProvider poiListsForUser:[self loggedUserMock]]) willReturn:@[[self poiListFake]]];
    __block NSArray *capturedResults;
    [self.sut userPoiListsWithSuccessBlock:^(NSArray *results) {
        capturedResults = results;
    }];
    assertThat(capturedResults, hasLengthOf(1));
}

1的长度和赝品之间的关系很难说。让我们也参数化伪造代码:

- (PoiListEntity *)poiListFakeWithName:(NSString *)name count:(NSNumber *)count {
    PoiListEntity *fake = [NSEntityDescription insertNewObjectForEntityForName:@"PoiListEntity" inManagedObjectContext:self.coreDataStack.managedObjectContext];
    fake.name = name;
    fake.poisCount = count;
    [fake addContributorsObject:[self loggedUserMock]];
    return fake;
}

有了它,我们可以编写更有趣的测试。

我想补充一点,"倾听测试"很重要。围绕核心数据有很多复杂的设置。这告诉我,如果你能重写一些独立于核心数据的东西——完全不知道它——一切都会简单得多。

最新更新