我对 expectationForNotification 的内容/时间有点困惑,而不是 expectationWithDescription 。我已经无法在swift中找到任何明确的例子来说明你何时以及如何处理这个电话。
我假设它可能会测试通知,但看起来它可能只是围绕整个addObserver()
通知中心呼叫的更方便的包装器。
有人可以简要解释一下它的用途,何时使用它,以及几行示例代码?
由于
答案 0 :(得分:24)
正如您已经想象的那样 expectationForNotification 是检查通知是否被引发的便利期望。
这个测试:
func testItShouldRaiseAPassNotificationV1() {
let expectation = expectationWithDescription("Notification Raised")
let sub = NSNotificationCenter.defaultCenter().addObserverForName("evPassed", object: nil, queue: nil) { (not) -> Void in
expectation.fulfill()
}
NSNotificationCenter.defaultCenter().postNotificationName("evPassed", object: nil)
waitForExpectationsWithTimeout(0.1, handler: nil)
NSNotificationCenter.defaultCenter().removeObserver(sub)
}
可以替换为:
func testItShouldRaiseAPassNotificationV2() {
expectationForNotification("evPassed", object: nil, handler: nil)
NSNotificationCenter.defaultCenter().postNotificationName("evPassed", object: nil)
waitForExpectationsWithTimeout(0.1, handler: nil)
}
您可以在Objc.io number中找到一个很好的解释。
答案 1 :(得分:1)
为了理解expectation(forNotification:, object:, handler:)
和expectation(description:)
之间的区别,我使用Swift 3构建了一个简单的XCTestCase
子类。
在这里,我们要测试发布BlockOperation
的{{1}}是否更新了我们班级的指定Notification
属性,请求值为50。
Int?
与expectation(description:)
addObserver(_:, selector:, name:, object:)
import XCTest
class AppTests: XCTestCase {
var testExpectation: XCTestExpectation?
var finalAmount: Int?
func testFinalAmount() {
let notificationName = Notification.Name(rawValue: "BlockNotification")
// Set self as an observer
let selector = #selector(updateFrom(notification:))
NotificationCenter.default.addObserver(self, selector: selector, name: notificationName, object: nil)
// Set expectation
testExpectation = expectation(description: "Did finish operation expectation")
// Set and launch operation block and wait for expectations
let operation = BlockOperation(block: {
NotificationCenter.default.post(name: notificationName, object: nil, userInfo: ["amount": 50])
})
operation.start()
waitForExpectations(timeout: 3, handler: nil)
// Asserts
XCTAssertNotNil(finalAmount)
XCTAssertEqual(finalAmount, 50)
}
func updateFrom(notification: Notification) {
if let amount = notification.userInfo?["amount"] as? Int {
self.finalAmount = amount
}
self.testExpectation?.fulfill()
}
}
与expectation(description:)
addObserver(forName:, object:, queue:, using:)
import XCTest
class AppTests: XCTestCase {
var finalAmount: Int?
func testFinalAmount() {
let notificationName = Notification.Name(rawValue: "BlockNotification")
// Set expectation
let testExpectation = expectation(description: "Did finish operation expectation")
// Set self as an observer
let handler = { (notification: Notification) -> Void in
if let amount = notification.userInfo?["amount"] as? Int {
self.finalAmount = amount
}
testExpectation.fulfill()
}
NotificationCenter.default.addObserver(forName: notificationName, object: nil, queue: nil, using: handler)
// Set and launch operation block and wait for expectations
let operation = BlockOperation(block: {
NotificationCenter.default.post(name: notificationName, object: nil, userInfo: ["amount": 50])
})
operation.start()
waitForExpectations(timeout: 3, handler: nil)
// Asserts
XCTAssertNotNil(finalAmount)
XCTAssertEqual(finalAmount, 50)
}
}
expectation(forNotification:, object:, handler:)
在我们的测试用例中使用import XCTest
class AppTests: XCTestCase {
var finalAmount: Int?
func testFinalAmount() {
let notificationName = Notification.Name(rawValue: "BlockNotification")
// Set expectation
let handler = { (notification: Notification) -> Bool in
if let amount = notification.userInfo?["amount"] as? Int {
self.finalAmount = amount
}
return true
}
expectation(forNotification: notificationName.rawValue, object: nil, handler: handler)
// Set and launch operation block and wait for expectations
let operation = BlockOperation(block: {
NotificationCenter.default.post(name: notificationName, object: nil, userInfo: ["amount": 50])
})
operation.start()
waitForExpectations(timeout: 3, handler: nil)
// Asserts
XCTAssertNotNil(finalAmount)
XCTAssertEqual(finalAmount, 50)
}
}
代替expectation(forNotification: String, object:, handler:)
提供了一些优势:
expectation(description:)
与addObserver(_:, selector:, name:, object:)
或#selector
一起使用,addObserver(forName:, object:, queue:, using:)
实例声明为我们类的属性或我们的测试方法的范围变量,并将其标记为在XCTestExpectation
的某个时刻已经满足答案 2 :(得分:1)
您不应该依赖UIKit的NotificationCenter。只有当您的类型将命令发送到正确的对象时,才创建类型的边界并进行测试。以下是如何使NotificationCenter采用您的代码的示例。 (我现在无法访问Xcode,所以可能会有一些错字)
protocol NotificationCenterProtocol {
func post(notification: Notification)
}
extension NotificationCenter: NotificationCenterProtocol {}
class SpyNotificationCenter: NotificationCenterProtocol {
var didPostNotification = false
func post(notification: Notification) {
didPostNotification = true
}
}