一尘不染

如何测试是否已触发UIControlEvents

swift

我有一个UIControl使用方法实现自定义的库,该方法将.valueChanged在调用时触发事件。我想测试该行为的方法。

我的自定义控件:

class MyControl: UIControl {
    func fire() {
        sendActions(for: .valueChanged)
    }
}

和测试:

import XCTest

class ControlEventObserver: NSObject {
    var expectation: XCTestExpectation!

    init(expectation anExpectation: XCTestExpectation) {
        expectation = anExpectation
    }

    func observe() {
        expectation.fulfill()
    }
}

class Tests: XCTestCase {
    func test() {
        let myExpectation = expectation(description: "event fired")
        let observer = ControlEventObserver(expectation: myExpectation)
        let control = MyControl()
        control.addTarget(observer, action: #selector(ControlEventObserver.observe), for: .valueChanged)
        control.fire()
        waitForExpectations(timeout: 1) { error in
            XCTAssertNil(error)
        }
    }
}

问题在于该observe方法永远不会被调用,因此expectation无法实现。

问题是:UIControlEvents在这种情况下,我们如何进行测试?也许我们需要以某种方式强制运行循环?

编辑1:请注意,由于我正在测试库,因此我的测试目标没有任何主机应用程序。当测试目标具有主机应用程序时,以上测试通过。


阅读 253

收藏
2020-07-07

共1个答案

一尘不染

Apple的UIControl文档指出:

当发生控件特定的事件时,控件立即调用任何关联的操作方法。 动作方法是通过当前的UIApplication对象调度的
,该对象在响应者链之后(如果需要)找到一个合适的对象来处理消息。

sendActions(for:)被称为一个UIControl,控制将调用UIApplicationsendAction(_:to:from:for:)该事件传递到准的目标。

由于我正在测试没有任何主机应用程序的库,因此没有UIApplication对象。因此,.valueChanged不会调度事件,也不会调用该observe方法。

2020-07-07