2016-10-04 38 views
0

我有一个库实现自定义UIControl的方法,该方法在调用时会触发一个.valueChanged事件。我想测试该行为的方法。如何测试UIControlEvents是否已被触发

我的自定义控件:

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?也许我们需要以某种方式强制runloop?

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

+1

这很奇怪我已经在我创建的项目中复制并粘贴了您的代码,并且期望已全满,测试成功通过。 – Wilson

+0

刚刚意识到这可能是因为我正在测试一个库。当我使用主机应用程序创建另一个测试目标时,上面的测试通过。 @WilsonB​​alderrama –

回答

4

Apple's documentation for UIControl指出:

当特定控制的事件发生时,控件调用任何相关 动作方法的时候了。 通过 当前的UIApplication对象调度操作方法,如果需要,可以在响应器链之后找到适当的对象来处理消息。

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

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

0

您正在测试方法内声明观察者对象。这意味着只要方法完成,它将从内存中释放,因此不会被调用。创建一个对Tests类中的课堂级观察员的引用,如下所示,它将起作用。

class Tests: XCTestCase { 

    var observer: ControlEventObserver! 
    func test() { 
     let myExpectation = expectation(description: "event fired") 
     self.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) 
     } 
    } 
} 

您还需要myExpectation & control以同样的方式其他事物也不会被所谓的声明。

+0

感谢您的回答。我认为这些对象没有被释放,因为我没有创建任何自动释放池。另外,我正在测试一个库,以便测试目标没有任何主机应用程序。我已经修改了我的问题以反映这一点。 –

相关问题