ios - 如何使用异步调用对 @IBAction 进行单元测试

标签 ios swift unit-testing xcode7 xctest

在下面的代码中,我想测试是否调用了“DisplayHelper.displayAlert”。我正在依赖注入(inject) DisplayHelperAuthService 模拟对象,并使用 PromiseKit

在我的 View Controller 中:

@IBAction func submitButtonPressed(sender: AnyObject) {
    AuthService.updateUser(["zipcode": self.zipcodeTextField.text!])
        .then { user -> Void in
             // sucess code
        }.error { error -> Void in
            self.DisplayHelper.displayAlert("Zipcode Not Found", message: "We can't find that zipcode... please try again.", callingViewController: self)
        }
}

以下是不起作用的测试:

func testSubmitButtonServerCantFindZipcode() {
    vc.zipcodeTextField.text = "00000"
    vc.submitButtonPressed(self)

    // called AuthService    (passes)
    XCTAssertEqual(authServiceMock.updateUserCalled, true)

    // called displayAlert (fails because tests run before DisplayAlert is called)
    XCTAssertEqual(displayHelperMock.displayAlertCalled, true)
}

如何让测试在断言之前等待所有代码执行?

最佳答案

使用 XCTest 测试异步代码时,您需要使用 XCTestExpectation .

您可以像这样重写测试代码:

let e = expectationWithDescription("display alert")
waitForExpectationsWithTimeout(3) { error in
    XCTAssertEqual(displayHelperMock.displayAlertCalled, true)
}

现在,使测试工作唯一缺少的部分是找到调用 expectation.fulfill() 的地方。最合适的位置是在您的 AuthService 模拟中,成功和失败回调运行之后。

如果我可以建议你一些事情,编写测试来断言是否已调用某些方法并不是一种安全的测试方法,因为你只是测试实现而不是行为。

更好的方法是独立测试这两个组件。测试AuthService 确保成功和失败路径均按预期执行,并测试DisplayHelper 以确保警报 View 实际上已添加到 View 层次结构中。

This article可能是一个有用的地方,可以开始了解单元测试警报的方式,以及 this post关于为什么以及如何避免模拟的好读物。

关于ios - 如何使用异步调用对 @IBAction 进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34254211/

相关文章:

ios - 在编辑模式下移除表格行上的删除按钮 ⛔️

ios - 如何在 Xcode 中使用带有 api key 的 api?

perl - 重构 perl sub 以提高可测试性

visual-studio - 为 nUnit 测试设置 Visual Studio 项目的最佳实践

ios - 推送到达时不播放自定义声音

ios - 如何使用 Objective-C 用两个 NSMutableArray 填充可扩展 TableView

ios - 在 ios6 上使用 Xcode 5 追踪僵尸

swift - 'valueForKeyPath:' 函数不支持

java - 单元测试失败: mockS3FileRead NullPointerException

ios - 位置跟踪器图标未显示在 map 上