nar*_*ner 6 unit-testing ios xctest 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)
}
}
Run Code Online (Sandbox Code Playgroud)
我为我的单元测试创建了一个包含以下代码的文件:
import XCTest
class AlertTest: XCTestCase {
func testAlert() {
let alert = presentAlert("Presented Alert", "This is an Alert!")
}
}
Run Code Online (Sandbox Code Playgroud)
但是,我一直收到错误"Use of unresolved identifier 'presentAlert'"
.public
在咨询了这个SO线程后,我尝试添加到我的扩展中:
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)
}
}
Run Code Online (Sandbox Code Playgroud)
在视图控制器中,我想要显示警报,这仍然是调用警报的正确方法,对吗?
self.presentAlert("Invalid URL", message: "Please try again")
Run Code Online (Sandbox Code Playgroud)
其次,根据你的评论,这就是我通过调用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();
}
Run Code Online (Sandbox Code Playgroud)
编辑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)
}
}
Run Code Online (Sandbox Code Playgroud)
这就是我试图从我的ViewController调用它的方式:
Presentable.presentAlert("Invalid URL", message: "Please try again")
Run Code Online (Sandbox Code Playgroud)
但是,我收到一个错误" 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();
}
Run Code Online (Sandbox Code Playgroud)
小智 6
正如@丹所提到的,你需要从调用它的实例的UIViewController
。如果可以避免的话,通常你不想在测试中实例化框架对象,所以这里有一些选项可以避免这种情况:
presentAlert
静态,这样你就可以UIViewController.presentAlert
presentAlert
一个免费的函数(不要放在扩展里)protocol Presentable {}
extension Presentable {
func presentAlert(title: String, message : String) { /* ... */ }
}
Run Code Online (Sandbox Code Playgroud)
然后,只要您需要,就可以extension UIViewController: Presentable {}
。在你的测试中,你可以只使用一个虚拟类。这种方法的额外好处是,如果需要,您可以在任何类型上重用该函数,而无需在不需要时全局公开它。
附录
当我们扩展协议时,我们说“任何实现这个协议的东西都将免费获得这个方法。” 这里的技巧是这个协议是空的,因此很容易“实现”。
extension YourViewController: Presentable {}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
4182 次 |
最近记录: |