在下面的代码中,我想测试是否调用了“DisplayHelper.displayAlert”。我正在依赖注入(inject) DisplayHelper
和 AuthService
模拟对象,并使用 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/