0

我开始使用 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 6waitForExpectation来管理异步方法。我想我做错了什么。

- (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 方法时,它应该返回我之前给出的内容。真的吗?谢谢

4

1 回答 1

1

我看不到异步代码。您只需要一个捕获结果的块,因此使用__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的长度和fake的关系很难说。让我们也参数化伪造代码:

- (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;
}

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

我确实想补充一点,“听测试”很重要。围绕 Core Data 有很多复杂的设置。这告诉我,如果你可以重写独立于 Core Data 的东西——完全不知道它——一切都会简单得多。

于 2015-02-10T03:11:58.113 回答