[英]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
的实例中调用它。 通常,如果可以避免,则不想在测试中实例化框架对象,因此,这里有一些避免这种情况的选项:
presentAlert
静态,以便您可以只使用UIViewController.presentAlert
presentAlert
为自由函数(不要将其放在扩展名中) protocol Presentable {}
extension Presentable {
func presentAlert(title: String, message : String) { /* ... */ }
}
然后,在需要时可以extension UIViewController: Presentable {}
。 在测试中,您可以只使用一个哑类。 这种方法的附加好处是,您可以根据需要在任何类型上重用该函数,而不必在不需要时全局公开它。
附录
当我们扩展协议时,我们说的是“实现该协议的任何人都可以免费获得此方法。” 这里的窍门是该协议为空,因此很容易“实现”。
extension YourViewController: Presentable {}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.