在Swift

时间:2016-08-12 19:23:01

标签: ios swift unit-testing xctest

我试图在Swift中为类扩展编写单元测试。类扩展本身将呈现具有指定标题和消息的UIAlert

extension UIViewController {

    func presentAlert(title: String, message : String) {
        let alertController = UIAlertController(title: title, message: message, preferredStyle: .Alert)
            alertController.addAction(UIAlertAction(title: "Close", style: UIAlertActionStyle.Default, handler: nil))

        UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(alertController, animated: true, completion: nil)

    }
}

我为单元测试创​​建了一个包含以下代码的文件:

import XCTest

class AlertTest: XCTestCase {

    func testAlert() {

        let alert = presentAlert("Presented Alert", "This is an Alert!")

    }

}

但是,我一直收到"Use of unresolved identifier 'presentAlert'"的错误。在咨询SO thread后,我尝试将public添加到我的扩展程序中:

public func presentAlert(title: String, message : String)

但仍然没有运气。任何人都有一些见解?

修改

根据@hkgumbs的回答,这是我当前的警报扩展代码:

import Foundation

protocol Presentable {}

extension UIViewController {

    public func presentAlert(title: String, message : String) {
        let alertController = UIAlertController(title: title, message: message, preferredStyle: .Alert)
            alertController.addAction(UIAlertAction(title: "Close", style: UIAlertActionStyle.Default, handler: nil))

        UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(alertController, animated: true, completion: nil)

    }
}

在视图控制器中,我想要显示警报,这仍然是调用警报的正确方法,对吗?

self.presentAlert("Invalid URL", message: "Please try again")

其次,根据您的评论,这就是我通过在虚拟值上调用Presentable而理解的内容,但由于SomethingPresentable没有成员PresentAlert,这是不正确的。我理解的地方出错了?

func testAlert() {

    let app = XCUIApplication()

    struct SomethingPresentable: Presentable {}

    SomethingPresentable.presentAlert("Presented Alert", message: "This is an Alert!")

    XCTAssert(app.alerts["Presented Alert"].exists)
    app.alerts["Presented Alert"].tap();

}

编辑2 @hkgumbs,根据您的最新评论,这就是我对扩展的内容:

import Foundation

protocol Presentable {}

extension Presentable {

    func presentAlert(title: String, message : String) {
        let alertController = UIAlertController(title: title, message: message, preferredStyle: .Alert)
            alertController.addAction(UIAlertAction(title: "Close", style: UIAlertActionStyle.Default, handler: nil))

        UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(alertController, animated: true, completion: nil)

    }
}

这就是我试图从我的ViewController调用它的方式:

Presentable.presentAlert("Invalid URL", message: "Please try again")

但是,我在类型presentAlert上收到"使用实例成员Self的错误;你的意思是使用Self类型的变量吗?"

然后,我猜这是测试的样子?

func testAlert() {

    let app = XCUIApplication()

    struct SomethingPresentable: Presentable {}

    SomethingPresentable.presentAlert("Presented Alert", message: "This is an Alert!")

    XCTAssert(app.alerts["Presented Alert"].exists)
    app.alerts["Presented Alert"].tap();

}

1 个答案:

答案 0 :(得分:4)

@dan所提到的,您需要从{em> UIViewController的实例中调用它。通常你不想在你的测试中实例化框架对象,如果你可以避免它,所以这里有一些选项来避免它:

  1. presentAlert设为静态,以便您可以UIViewController.presentAlert
  2. presentAlert成为免费功能(不要将其放入扩展程序中)
  3. 扩展协议 - 我认为这是最干净的选择
  4. protocol Presentable {}
    
    extension Presentable {
        func presentAlert(title: String, message : String) { /* ... */ }
    }
    

    然后,只要您需要它,您就可以extension UIViewController: Presentable {}。在测试中,您可以使用虚拟类。这种方法的另一个好处是,如果需要,您可以在任何类型上重复使用该功能,而不会在您没有全局曝光时使用。

    <强>附录

    当我们扩展协议时,我们说&#34;任何实现此协议的方法都将免费获得此方法。&#34;这里的诀窍是这个协议是空的,因此很容易实现。&#34;

    extension YourViewController: Presentable {}