我正在尝试单元测试UIViewController中按钮点击的连接,但我发现这些测试失败了,尽管运行中的应用程序中的代码运行良好。
我简化了失败的测试,删除了视图控制器,然后简单地离开了:
import XCTest
class ButtonTest: XCTestCase {
var gotTap: XCTestExpectation!
func test_givenButtonWithTargetForTapAction_whenButtonIsSentTapAction_thenTargetIsCalled() {
gotTap = expectation(description: "Button tap recieved")
let button = UIButton()
button.addTarget(self, action: #selector(tap), for: .touchUpInside)
button.sendActions(for: .touchUpInside)
// Fails.
wait(for: [gotTap], timeout: 0.1)
}
@objc func tap() {
gotTap.fulfill()
}
}这项测试确实:
button.sendActions(for: .touchUpInside)点击按钮失败的原因是:
异步等待失败:超过了0.1秒的超时,未实现预期:“按钮点击接收”。
我不想为此使用UI测试。它们的执行速度要慢很多数量级,在这里,单元测试应该是理想的。
问题
UIButton操作发送需要对响应链进行额外设置而导致失败吗?还是这里不存在的运行循环?还是别的什么?如何在不实例化完整运行的应用程序的情况下,在单元测试中将其设置为最低限度?发布于 2019-10-23 10:57:04
关于控制事件的问题具有控制事件需要UIApplication实例才能发送操作的回答。不幸的是,这个问题并没有说明如何做到这一点。
还有一些代码这里使用swizzling来修补在UIControl上发送的操作的实现,这样它就不会委托给UIApplication。因为它依赖于覆盖initialize,所以它并不是最近才构建的--不过,这可能是可以修复的。
我采取的方法是在UIControl上实现一个扩展,以便在测试中使用,该扩展提供了一个方法simulateEvent(_ event: UIControl.Event),如下所示:
extension UIControl {
func simulateEvent(_ event: UIControl.Event) {
for target in allTargets {
let target = target as NSObjectProtocol
for actionName in actions(forTarget: target, forControlEvent: event) ?? [] {
let selector = Selector(actionName)
target.perform(selector)
}
}
}
}可以对此进行改进,以正确检查选择器,并确定是否也应该发送发送方和事件,但这是概念的合理证明,允许在XCUnitTest中发送按钮。我还觉得它是非侵入性的,并且接受了一个单元测试没有在一个完整的应用程序环境中运行的事实,所以测试不能使用完整的响应程序处理。
https://stackoverflow.com/questions/58519479
复制相似问题