Reputation: 44720
I'd like to unit test some UNUserNotificationCenterDelegate
methods, especially userNotificationCenter(_, willPresent:, withCompletionHandler:)
To do that, I'd have to create an instance of UNNotification
, but that's not really possible because it only has an initWithCoder
initializer. What to do?
This is an example of what I'd like to test:
func userNotificationCenter(
_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
) {
completionHandler(.sound)
}
Upvotes: 1
Views: 1050
Reputation: 234
You can use class_createInstance(UNNotification.classForKeyedArchiver() ...)and cast the value as UNNotification
If you want to manipulate its content and date members you can subclass UNNotification and use this same formula «changing class name and cast» to create it, then you override those members- which are open- and return whatever you want
Upvotes: 0
Reputation: 44720
Thanks to this README and the private iOS headers here, I came up with this solution:
func testUserNotificationCenterDelegate() throws {
// Create the notification content
let notificationContent = UNMutableNotificationContent()
notificationContent.title = "Test"
notificationContent.userInfo = ["someKey": "someValue"]
// Create a notification request with the content
let notificationRequest = UNNotificationRequest(identifier: "test", content: notificationContent, trigger: UNTimeIntervalNotificationTrigger(timeInterval: 0.1, repeats: false))
// Use private method to create a UNNotification from the request
let selector = NSSelectorFromString("notificationWithRequest:date:")
let unmanaged = UNNotification.perform(selector, with: notificationRequest, with: Date())
let notification = unmanaged?.takeUnretainedValue() as! UNNotification
// Test the method
let callbackExpectation = XCTestExpectation(description: "Callback")
pushService.userNotificationCenter(UNUserNotificationCenter.current(), willPresent: notification) { (options) in
XCTAssertEqual(options, .sound)
callbackExpectation.fulfill()
}
wait(for: [callbackExpectation], timeout: 2.0)
}
In the code above, pushService
is an instance of a class that conforms to the UNUserNotificationCenterDelegate
protocol. Elsewhere in my code, I set that instance as the center's delegate: UNUserNotificationCenter.current().delegate = pushService
.
Enjoy!
Upvotes: 2