假设我有这样的代码:
class Foo {
private let nc: NotificationCenter
init(nc: NotificationCenter = .default) {
self.nc = nc
nc.addObserver(forName: Notification.Name.Foo, object: nil, queue: .main) { _ in
Task { [weak self] in
self?.doSomething()
}
}
}
deinit {
nc.removeObserver(self, name: Notification.Name.Foo, object: nil)
}
@objc
private func doSomething() async {
// triggers some async code
}
}
我想要编写一个单元测试,以确保在释放类时删除该观察器.
苹果公司的文件规定:
如果您使用addWatch(forName:Object:Queue:Using:)来创建您的观察器,则应在系统释放addWatch(forName:Object:Queue:Using:)指定的任何对象之前调用此方法或移除该方法或删除该方法(_:name:Object:).
我曾嘲笑过一个通知中心:
class MockNotificationCenter: NotificationCenter {
var notifications: [NSNotification.Name?] = []
override func addObserver(
forName name: NSNotification.Name?,
object obj: Any?,
queue: OperationQueue?,
using block: @escaping (Notification) -> Void) -> NSObjectProtocol
{
notifications.append(name)
return super.addObserver(forName: name, object: obj, queue: queue, using: block)
}
override func removeObserver(
_ observer: Any,
name aName: NSNotification.Name?,
object anObject: Any?
) {
notifications = notifications.filter { $0 != aName }
super.removeObserver(observer, name: aName, object: anObject)
}
下面是我的单元测试:
func testDeinit_DoesRemoveObserver() {
// Given
var sut: Foo?
let mockNC = MockNotificationCenter()
// When
sut = Foo(notificationCenter: mockNC)
// Then
XCTAssertEqual(mockNC.notifications.count, 1) // Succeeds
// When
sut = nil
// Then
XCTAssertEqual(mockNC.notifications.count, 0) // Fails
}
XCTAssertEqual失败:("1")不等于("0")
我如何解决这个问题,以断言观察者在我的观察对象解除分配后已从通知中心移除?