在 Swift 中測試 UIAlertController的方法_Swift

來源:互聯網
上載者:User

最近我讀了一篇在 Objective-C 中使用 control swizzling 測試 UIAlertController 的 文章 。這樣的文章總是促使我尋找一種不使用 control swizzling 也可以測試同樣東西的方法。雖然,我知道 swizzling 是開發人員的一個非常有力的工具,但我個人是儘可能去避免去使用它的。事實上,在最近的六年時間裡,我只在一個應用上用了 swizzling。所以我相信我們現在可以不使用 swizzling 來實現測試。

那麼問題來了,如何在 Swift 中不使用 swizzling 來對 UIAlertController 進行測試?

我們先從我們要測試的代碼開始吧。我已經添加一個按鈕到 Storyboard 中。(我之所以使用 Storyboard 為了讓那些不想用代碼寫介面的小夥伴有個更直觀的感受)當按下這個按鈕就會出現一個彈窗(alert),它有標題、訊息內容,還有兩個按鈕,分別是 OK 和取消(Cancel)。

下面是這段代碼:

import UIKitclass ViewController: UIViewController { var actionString: String? @IBAction func showAlert(sender: UIButton) {  let alertViewController = UIAlertController(title: "Test Title", message: "Message", preferredStyle: .Alert)  let okAction = UIAlertAction(title: "OK", style: .Default) { (action) -> Void in   self.actionString = "OK"  }  let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel) { (action) -> Void in   self.actionString = "Cancel"  }  alertViewController.addAction(cancelAction)  alertViewController.addAction(okAction)  presentViewController(alertViewController, animated: true, completion: nil) }}

注意,在這個例子中彈窗動作沒有做什麼具體的操作,他們只表示能驗證單元測試。

讓我們開始一個簡單的測試:測試這個彈窗控制器的標題和訊息內容。

測試的代碼如下:

import XCTest@testable import TestingAlertExperimentclass TestingAlertExperimentTests: XCTestCase { var sut: ViewController! override func setUp() {  super.setUp()  sut = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController() as! ViewController  UIApplication.sharedApplication().keyWindow?.rootViewController = sut } override func tearDown() {  // Put teardown code here. This method is called after the invocation of each test method in the class.  super.tearDown() }}```

我們需要設定 sut 為根視圖控制器,否則視圖控制器不能彈出這個彈窗視圖控制器。

添加 UIAlertController 測試標題的代碼如下:

```Swiftfunc testAlert_HasTitle() { sut.showAlert(UIButton()) XCTAssertTrue(sut.presentedViewController is UIAlertController) XCTAssertEqual(sut.presentedViewController?.title, "Test Title")}``` 

這很簡單。現在讓我們測試 UIAlertController 的取消按鈕。這裡有一個問題:無法擷取彈窗動作的閉包。因此我們需要類比彈窗動作,為了儲存這個 handler 並在測試中調用它,看彈窗動作是否和我們預期的一樣。在測試案例中添加這樣一個類:

```Swiftclass MockAlertAction : UIAlertAction { typealias Handler = ((UIAlertAction) -> Void) var handler: Handler? var mockTitle: String? var mockStyle: UIAlertActionStyle convenience init(title: String?, style: UIAlertActionStyle, handler: ((UIAlertAction) -> Void)?) {  self.init()  mockTitle = title  mockStyle = style  self.handler = handler } override init() {  mockStyle = .Default  super.init() }}

這個類比類的主要工作是捕獲 handler 塊,以備後用。現在我們需要將這個類比的類插入到實現代碼中。將視圖控制器中的代碼換成下面這個:

import UIKitclass ViewController: UIViewController { var Action = UIAlertAction.self var actionString: String? @IBAction func showAlert(sender: UIButton) {  let alertViewController = UIAlertController(title: "Test Title", message: "Message", preferredStyle: .Alert)  let okAction = Action.init(title: "OK", style: .Default) { (action) -> Void in   self.actionString = "OK"  }  let cancelAction = Action.init(title: "Cancel", style: .Cancel) { (action) -> Void in   self.actionString = "Cancel"  }  alertViewController.addAction(cancelAction)  alertViewController.addAction(okAction)  presentViewController(alertViewController, animated: true, completion: nil) }}```

我們添加了一個類變數`Action`,並設定為`UIAlertAction.self`。這個變數我們會在初始化彈窗動作時使用。這就能讓我們在測試時可以重寫它。像這樣:

```Swiftfunc testAlert_FirstActionStoresCancel() { sut.Action = MockAlertAction.self sut.showAlert(UIButton()) let alertController = sut.presentedViewController as! UIAlertController let action = alertController.actions.first as! MockAlertAction action.handler!(action) XCTAssertEqual(sut.actionString, "Cancel")}

首先我們插入了這個彈窗動作。之後我們調用代碼彈出彈窗視圖控制器。我們從呈現的視圖控制器中擷取了取消動作,並且成功調用了捕獲的 handler 塊。最後一步就是去斷言當前的動作是否和我們預期的一樣。

就是這樣,一種很簡單的又不使用 swizzling 來測試 UIAlertViewController 的方式。

以上內容是關於在 Swift 中測試 UIAlertController的方法,希望對大家有用。

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.