繁体   English   中英

在Swift中为类扩展编写单元测试

[英]Writing a unit-test for a class extension in Swift

我正在尝试为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'"收到"Use of unresolved identifier 'presentAlert'" 我在咨询此SO线程后尝试将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")

但是,我收到错误消息“在类型Self上使用实例成员presentAlert ;您的意思是改为使用类型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();

}

正如@dan所暗示的那样,您需要从UIViewController 的实例中调用它。 通常,如果可以避免,则不想在测试中实例化框架对象,因此,这里有一些避免这种情况的选项:

  1. presentAlert静态,以便您可以只使用UIViewController.presentAlert
  2. presentAlert为自由函数(不要将其放在扩展名中)
  3. 而是扩展协议–我认为这是最干净的选择

protocol Presentable {}

extension Presentable {
    func presentAlert(title: String, message : String) { /* ... */ }
}

然后,在需要时可以extension UIViewController: Presentable {} 在测试中,您可以只使用一个哑类。 这种方法的附加好处是,您可以根据需要在任何类型上重用该函数,而不必在不需要时全局公开它。

附录

当我们扩展协议时,我们说的是“实现该协议的任何人都可以免费获得此方法。” 这里的窍门是该协议为空,因此很容易“实现”。

extension YourViewController: Presentable {}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM