gpt4 book ai didi

ios - 单元测试 iOS 10 通知

转载 作者:技术小花猫 更新时间:2023-10-29 10:46:08 27 4
gpt4 key购买 nike

在我的应用程序中,我希望断言已以正确的格式添加了通知。我通常会使用依赖项注入(inject)来执行此操作,但我想不出一种方法来测试新的 UNUserNotificationCenter API。

我开始创建一个模拟对象来捕获通知请求:

import Foundation
import UserNotifications

class NotificationCenterMock: UNUserNotificationCenter {
var request: UNNotificationRequest? = nil
override func add(_ request: UNNotificationRequest, withCompletionHandler completionHandler: ((Error?) -> Void)? = nil) {
self.request = request
}
}

但是,UNUserNotificationCenter 没有可访问的初始值设定项,我无法实例化模拟。

我什至不确定我是否可以通过添加通知请求和获取当前通知来进行测试,因为测试需要在模拟器上请求许可,这会使测试停止。目前,我已将通知逻辑重构为包装器,因此我至少可以在整个应用程序中模拟它并手动测试。

我有比手动测试更好的选择吗?

最佳答案

您可以为您正在使用的方法创建一个协议(protocol),并在 UNUserNotificationCenter 上进行扩展以符合它。该协议(protocol)将充当原始 UNUserNotificationCenter 实现和您的模拟对象之间的“桥梁”,以替换其方法实现。

这是我在 Playground 上写的示例代码,运行良好:

/* UNUserNotificationCenterProtocol.swift */

// This protocol allows you to use UNUserNotificationCenter, and replace the implementation of its
// methods in you test classes.
protocol UNUserNotificationCenterProtocol: class {
// Declare only the methods that you'll be using.
func add(_ request: UNNotificationRequest,
withCompletionHandler completionHandler: ((Error?) -> Void)?)
}

// The mock class that you'll be using for your test classes. Replace the method contents with your mock
// objects.
class MockNotificationCenter: UNUserNotificationCenterProtocol {

var addRequestExpectation: XCTestExpectation?

func add(_ request: UNNotificationRequest,
withCompletionHandler completionHandler: ((Error?) -> Void)?) {
// Do anything you want here for your tests, fulfill the expectation to pass the test.
addRequestExpectation?.fulfill()
print("Mock center log")
completionHandler?(nil)
}
}

// Must extend UNUserNotificationCenter to conform to this protocol in order to use it in your class.
extension UNUserNotificationCenter: UNUserNotificationCenterProtocol {
// I'm only adding this implementation to show a log message in this example. In order to use the original implementation, don't add it here.
func add(_ request: UNNotificationRequest, withCompletionHandler completionHandler: ((Error?) -> Void)?) {
print("Notification center log")
completionHandler?(nil)
}
}

/* ExampleClass.swift */

class ExampleClass {

// Even though the type is UNUserNotificationCenterProtocol, it will take UNUserNotificationCenter type
// because of the extension above.
var notificationCenter: UNUserNotificationCenterProtocol = UNUserNotificationCenter.current()

func doSomething() {
// Create a request.
let content = UNNotificationContent()
let request = UNNotificationRequest(identifier: "Request",
content: content,
trigger: nil)
notificationCenter.add(request) { (error: Error?) in
// completion handler code
}
}
}

let exampleClass = ExampleClass()
exampleClass.doSomething() // This should log "Notification center log"

EDITED:
/* TestClass.Swift (unit test class) */

class TestClass {
// Class being tested
var exampleClass: ExampleClass!
// Create your mock class.
var mockNotificationCenter = MockNotificationCenter()

func setUp() {
super.setUp()
exampleClass = ExampleClass()
exampleClass.notificationCenter = mockNotificationCenter
}

func testDoSomething() {
mockNotificationCenter.addRequestExpectation = expectation(description: "Add request should've been called")
exampleClass.doSomething()
waitForExpectations(timeout: 1)
}
}
// Once you run the test, the expectation will be called and "Mock Center Log" will be printed

请记住,每次使用新方法时,都必须将其添加到协议(protocol)中,否则编译器会报错。

希望这对您有所帮助!

关于ios - 单元测试 iOS 10 通知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40862551/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com