In a Library Test Bundle (without a Test Host), the standard UIControl method sendActionsForControlEvents: does not work. To trigger code paths that normally run when a user interacts with a control, you must use a custom implementation that manually iterates through targets and actions.
Objective-C Implementation
You can use the following ub_sendActionsForControlEvents: method. Warning: Ensure this category is only visible within your unit tests to avoid polluting your production codebase.
Swift Implementation
If you are using Swift, you can use the testSendActions(for:toTarget:) extension.
Note: If any of the targets in allTargets do not subclass NSObject, the testSendActions(for:) method will crash. In such cases, call testSendActions(for:toTarget:) directly for each specific target.
import UIKit
public extension UIControl {
/// Note: if any of the targets in `allTargets` do not subclass NSObject, this will crash.
/// You should directly call `testSendActions(for:toTarget:)` for each target instead.
///
/// - Parameter controlEvent: The control events to send actions.
func testSendActions(
for controlEvent: UIControl.Event
) {
for target in allTargets {
testSendActions(for: controlEvent, toTarget: target as AnyObject)
}
}
/// Send an action for a given control event to a target.
/// - Parameters:
/// - controlEvent: A control event to send.
/// - target: The target to send it to.
func testSendActions(
for controlEvent: UIControl.Event,
toTarget target: AnyObject
) {
guard let actions = actions(forTarget: target, forControlEvent: controlEvent) else {
return
}
for action in actions {
_ = target.perform(Selector(action), with: self)
}
}
}