首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >单元测试iOS 10通知

单元测试iOS 10通知
EN

Stack Overflow用户
提问于 2016-11-29 09:46:19
回答 4查看 6.1K关注 0票数 17

在我的应用程序中,我希望断言已以正确的格式添加了通知。我通常会使用依赖注入来实现这一点,但是我想不出一种方法来测试新的UNUserNotificationCenter API。

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

代码语言:javascript
复制
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没有可访问的初始化器,我无法实例化模拟。

我甚至不确定我是否能够通过添加通知请求和获取当前通知来进行测试,因为测试需要在模拟器上请求权限,这会使测试陷入停顿。目前,我已经将通知逻辑重构为一个包装器,以便至少可以在整个应用程序中模拟并手动测试。

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

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2017-05-12 03:45:11

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

下面是我在操场上编写的示例代码,运行良好:

代码语言:javascript
复制
/* 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

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

希望这能有所帮助!

票数 25
EN

Stack Overflow用户

发布于 2020-02-04 14:32:13

您可以利用UNUserNotificationCenter,然后在返回的settings上使用setValue

代码语言:javascript
复制
UNUserNotificationCenter.current().getNotificationSettings(completionHandler: { settings in
    let status: UNAuthorizationStatus = .authorized
    settings.setValue(status.rawValue, forKey: "authorizationStatus")
    completionHandler(settings)
})
票数 3
EN

Stack Overflow用户

发布于 2022-02-11 06:21:51

我设法使用下面的方法来模拟UNNotificationSettings

代码语言:javascript
复制
let object = UIView()
let data = try! NSKeyedArchiver.archivedData(withRootObject: object, requiringSecureCoding: false)
let coder = try! NSKeyedUnarchiver(forReadingFrom: data)
let setting = UNNotificationSettings(coder: coder)
setting?.setValue(UNAuthorizationStatus.notDetermined.rawValue, forKey: "authorizationStatus")
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40862551

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档