一个更复杂但可能更面向未来的解决方案是使用接缝。有关接缝的更多信息,请阅读https://qualitycoding.org/mocking-standalone-functions/。我们可以使用同样的技术来模拟初始化器。首先,将以下内容添加到您的项目中:
import UIKit
let defaultUITableViewRowActionInit: (UITableViewRowAction.Style, String?, @escaping (UITableViewRowAction, IndexPath) -> Void) -> UIKit.UITableViewRowAction = { style, title, handler in
return UIKit.UITableViewRowAction(style: style, title: title, handler: handler)
}
var uiTableViewRowActionInit = defaultUITableViewRowActionInit
func UITableViewRowAction(style: UITableViewRowAction.Style, title: String?, handler: @escaping (UITableViewRowAction, IndexPath) -> Void) -> UIKit.UITableViewRowAction {
return uiTableViewRowActionInit(style, title, handler)
}
从这里开始,对 UITableVeiwRowAction 的调用将通过我们的函数而不是普通的初始化程序。在正常的 prod 使用期间,行为将是相同的。对于测试,我们现在可以先添加一个 mock:
class UITableViewRowActionMock: UITableViewRowAction {
var passedStyle: UITableViewRowAction.Style
var passedTitle: String?
var passedHandler: (UITableViewRowAction, IndexPath) -> Void
init(style: UITableViewRowAction.Style, title: String?, handler: @escaping (UITableViewRowAction, IndexPath) -> Void) {
passedStyle = style
passedTitle = title
passedHandler = handler
}
}
这个类只捕获传递给它的参数,包括块。从这里开始,我们需要我们的测试设置和拆卸来设置和拆卸接缝:
override func setUp() {
super.setUp()
// CODE ...
uiTableViewRowActionInit = { style, title, handler in
return UITableViewRowActionMock(style: style, title: title, handler: handler)
}
}
override func tearDown() {
// CODE ...
uiTableViewRowActionInit = defaultUITableViewRowActionInit
super.tearDown()
}
从那里,我们可以运行我们的测试:
func testEditActionSomehow() {
let indexPath = IndexPath(row: 0, section: 0)
// here I just grab, first, feel free to do something more complicated
guard let action = sut.tableView(sut.tableView, editActionsForRowAt: indexPath)?.first as? UITableViewRowActionMock else {
XCTFail("Unexpected type")
return
}
action.passedHandler(action, indexPath)
//
在此处添加断言代码 }
但是,如果您有很多案例要测试,您可能希望将大部分代码从您的操作中提取到更可测试的地方。