objective-c – iOS – 单元测试Asynchoronous代码

我试图测试的方法部分如下:

- (void)configureTableFooterView {
    dispatch_async(dispatch_get_main_queue(), ^{
        self.tableView.tableFooterView = nil;

        if ([self.parser.resultSet isLastPage]) {
            return;
        }
    });
}

我编写了单元测试如下:

- (void)testTableFooterViewConfigurationAfterLastPageLoaded {

    id mockTableView = OCMClassMock([GMGFlatTableView class]);

    OCMExpect([mockTableView setTableFooterView:[OCMArg isNil]]);

    id resultSet = OCMClassMock([GMGResultSetInfo class]);

    OCMStub([resultSet isLastPage]).andReturn(YES);

    OCMStub([self.mockParser resultSet]).andReturn(resultSet);

    id partialMockSUT = OCMPartialMock(self.sut);

    OCMStub([partialMockSUT tableView]).andReturn(mockTableView);

    [self.sut configureTableFooterView];

    OCMVerifyAllWithDelay(mockTableView, 2.0);

    //OCMVerifyAllWithDelay(partialMockSUT, 2.0); 
}

我在同一个类中有另一个测试,它在主线程上的dispatch_async调用中测试相同的东西.该测试中的测试期望和验证设置与此匹配.当测试通过时,这个测试在延迟验证步骤中陷入无限循环.

有趣的是,如果我只运行这个1测试,它会解决任何问题.它只有当这个测试与其他测试一起运行时才能看到问题.

更新:

In unit test, execute the block passed in queue with dispatch_asyc

这是一篇更相关的帖子.但是,这几乎与原始测试方法完全相同:

- (void)testTableFooterViewConfigurationAfterLastPageLoaded {

    id mockTableView = OCMClassMock([GMGFlatTableView class]);

    OCMExpect([mockTableView setTableFooterView:[OCMArg isNil]]);

    id resultSet = OCMClassMock([GMGResultSetInfo class]);

    OCMStub([resultSet isLastPage]).andReturn(YES);

    OCMStub([self.mockParser resultSet]).andReturn(resultSet);

    id partialMockSUT = OCMPartialMock(self.sut);

    OCMStub([partialMockSUT tableView]).andReturn(mockTableView);

    [self.sut configureTableFooterView];

    [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]];

    OCMVerifyAll(mockTableView);
}

当作为套件运行时,NSRunLoop的行与EXC_BAD_ACCESS崩溃,但运行良好!

最佳答案 您可以围绕dispatch_async创建类包装器,并将其作为依赖项传递.你也可以制作假包装,并在测试中传递它.如果您有兴趣,我可以提供更详细的解释.

点赞