Skip to content

Commit 4960261

Browse files
committed
Don't call a notification expectation handler after the expectation has expired
1 parent a431376 commit 4960261

File tree

2 files changed

+29
-8
lines changed

2 files changed

+29
-8
lines changed

Sources/XCTest/XCTestCase.swift

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -327,27 +327,35 @@ extension XCTestCase {
327327
let expectation = self.expectationWithDescription("Expect notification '\(notificationName)' from " + objectDescription)
328328
// Start observing the notification with specified name and object.
329329
var observer: NSObjectProtocol? = nil
330+
func removeObserver() {
331+
if let observer = observer as? AnyObject {
332+
NSNotificationCenter.defaultCenter().removeObserver(observer)
333+
}
334+
}
335+
336+
weak var weakExpectation = expectation
330337
observer = NSNotificationCenter
331338
.defaultCenter()
332339
.addObserverForName(notificationName,
333340
object: objectToObserve,
334341
queue: nil,
335342
usingBlock: {
336343
notification in
344+
guard let expectation = weakExpectation else {
345+
removeObserver()
346+
return
347+
}
348+
337349
// If the handler is invoked, the test will
338350
// only pass if true is returned.
339351
if let handler = handler {
340352
if handler(notification) {
341353
expectation.fulfill()
342-
if let observer = observer as? AnyObject {
343-
NSNotificationCenter.defaultCenter().removeObserver(observer)
344-
}
354+
removeObserver()
345355
}
346356
} else {
347357
expectation.fulfill()
348-
if let observer = observer as? AnyObject {
349-
NSNotificationCenter.defaultCenter().removeObserver(observer)
350-
}
358+
removeObserver()
351359
}
352360
})
353361

Tests/Functional/Asynchronous/Notifications/Handler/main.swift

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,29 @@ class NotificationHandlerTestCase: XCTestCase {
3333
NSNotificationCenter.defaultCenter().postNotificationName("returnTrue", object: nil)
3434
waitForExpectationsWithTimeout(0.1, handler: nil)
3535
}
36+
37+
// CHECK: Test Case 'NotificationHandlerTestCase.test_notificationNameIsObservedAfterTimeout_handlerIsNotCalled' started.
38+
// CHECK: .*/Tests/Functional/Asynchronous/Notifications/Handler/main.swift:\d+: error: NotificationHandlerTestCase.test_notificationNameIsObservedAfterTimeout_handlerIsNotCalled : Asynchronous wait failed - Exceeded timeout of 0.1 seconds, with unfulfilled expectations: Expect notification 'note' from any object
39+
// CHECK: Test Case 'NotificationHandlerTestCase.test_notificationNameIsObservedAfterTimeout_handlerIsNotCalled' failed \(\d+\.\d+ seconds\).
40+
func test_notificationNameIsObservedAfterTimeout_handlerIsNotCalled() {
41+
expectationForNotification("note", object: nil, handler: { _ in
42+
XCTFail("Should not call the notification expectation handler")
43+
return true
44+
})
45+
waitForExpectationsWithTimeout(0.1, handler: nil)
46+
NSNotificationCenter.defaultCenter().postNotificationName("note", object: nil)
47+
}
3648

3749
static var allTests: [(String, NotificationHandlerTestCase -> () throws -> Void)] {
3850
return [
3951
("test_notificationNameIsObserved_handlerReturnsFalse_andFails", test_notificationNameIsObserved_handlerReturnsFalse_andFails),
4052
("test_notificationNameIsObserved_handlerReturnsTrue_andPasses", test_notificationNameIsObserved_handlerReturnsTrue_andPasses),
53+
("test_notificationNameIsObservedAfterTimeout_handlerIsNotCalled", test_notificationNameIsObservedAfterTimeout_handlerIsNotCalled),
4154
]
4255
}
4356
}
4457

4558
XCTMain([testCase(NotificationHandlerTestCase.allTests)])
4659

47-
// CHECK: Executed 2 tests, with 1 failure \(0 unexpected\) in \d+\.\d+ \(\d+\.\d+\) seconds
48-
// CHECK: Total executed 2 tests, with 1 failure \(0 unexpected\) in \d+\.\d+ \(\d+\.\d+\) seconds
60+
// CHECK: Executed 3 tests, with 2 failures \(0 unexpected\) in \d+\.\d+ \(\d+\.\d+\) seconds
61+
// CHECK: Total executed 3 tests, with 2 failures \(0 unexpected\) in \d+\.\d+ \(\d+\.\d+\) seconds

0 commit comments

Comments
 (0)