模拟UNNotificationResponse和UNNotification(以及其他将init()标记为不可用的iOS平台类)

And*_*ing 6 tdd mocking swift

我需要进行模拟UNNotificationResponseUNNotification以便可以测试我的实现:

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Swift.Void)

但是,我无法对这些类进行有效的子类化,因为它们init()被专门标记为unavailable,如果尝试尝试,将导致如下编译错误:

/Path/to/PushClientTests.swift:38:5: Cannot override 'init' which has been marked unavailable

在这里可以采取哪些替代方法?我研究了面向协议的编程路线,但是由于我不控制被调用的API,因此无法修改它以接受要编写的协议。

aca*_*ano 9

要做到这一点,请执行以下操作。

在调试时获取对象的真实示例并使用模拟器保存在文件系统中。

func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification,
                                withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void) {

let encodedObject = NSKeyedArchiver.archivedData(withRootObject: notification)

let  path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] + "/notification.mock"

fileManager.createFile(atPath: path, contents: encodedObject, attributes: nil)


Run Code Online (Sandbox Code Playgroud)

在 Mac 中找到对象并将文件添加到与测试类相同的目标中。

现在在您的测试中取消存档。


let path = Bundle(for: type(of: self)).path(forResource: "notification", ofType: "mock")

let data = FileManager.default.contents(atPath: path ?? "")

let notification = NSKeyedUnarchiver.unarchiveObject(with: data ?? Data()) as? UNNotification

Run Code Online (Sandbox Code Playgroud)


Ili*_*rim 1

简短的回答:你不能!

相反,分解你的实现

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Swift.Void)
Run Code Online (Sandbox Code Playgroud)

并测试您从那里调用的方法。

测试愉快:)