在 XCTestCase 的 setUp() 中等待多个异步调用

Posted

技术标签:

【中文标题】在 XCTestCase 的 setUp() 中等待多个异步调用【英文标题】:Wait for multiple async calls in setUp() of XCTestCase 【发布时间】:2017-02-16 14:56:13 【问题描述】:

在让test() 方法运行之前,我需要执行多个调用。我有一个完成块,我正在使用waitForExpectations()。由于有多个异步调用,我使用了一个计数器。我让expectation.fulfill() 仅在计数器达到调用次数时才发生。

override func setUp() 
    super.setUp()

    let exp = expectation(description: "waitForSetUp")
    var counter = 0

    // Issue an async request
    self.addEventToCalendar(title: "Test1", description: "Description test1", startDate: NSDate().addingTimeInterval(-36000), endDate: NSDate())(success, error) in
        if (success) && (error == nil) 
            counter = counter + 1
            if(counter == 2)exp.fulfill()
        
    

    self.addEventToCalendar(title: "Test2", description: "Description test2", startDate: NSDate(), endDate: NSDate().addingTimeInterval(36000))(success, error) in
        if (success) && (error == nil) 
            counter = counter + 1
            if(counter == 2)exp.fulfill()
        
    

    waitForExpectations(timeout: 40, handler: nil)        

这种结构不起作用。 test() 方法有时会在调用返回之前运行(并非总是如此)。

如何让setUp() 等待返回多个异步调用?

【问题讨论】:

您是否尝试过实现处理程序并检查可能的错误? 【参考方案1】:

我也遇到过类似的情况。我最终做的解决方案是调用几个函数,这些函数增加了对我的先决条件的期望,并将期望的超时设置为一个合理的值。在期望的完成处理程序中,我触发了我的设置算法的下一步。在所有初步步骤都通过后,我开始实际的测试逻辑。

将link 附加到 Apple Docs。

编辑:请看下面的示例代码:

class CommonTests: XCTestCase 
    var validate: XCTestExpectation? = nil

    func testMytest()         
      validate(completion: 
        loadSomeStuff(completion:  (list: [Stuff]?) in
          // actual test
        
      )
    

    func validate(completion: @escaping ()->()) 
        self.validateExpectation = self.expectation(description: "Setup")
        // async operation can be fired here
        // or if already started from somewhere else just wait for it to complete


        self.waitForExpectations(timeout: 60)  (error: Error?) in
            XCTAssert((error == nil), error?.localizedDescription ?? "Failed with unknown error")
            completion()
        
    

    func validateAsyncCompleted() 
      self.validateExpectation?.fulfill()
    

    func loadStuff(completion: @escaping ([Stuff]?)->()) 

      // possible place for assertion or some other checks

      let expectation = self.expectation(description: "loading")
      DispatchQueue.global().async 

        let result: [Stuff]? = nil
        // load operation

        expectation.fulfill()
        completion(result)
      

      self.waitForExpectations(timeout: 90)   (error: Error?) in
        XCTAssert((error == nil), error?.localizedDescription ?? "load - failed with unknown error")
      
    

注意:期望有两种方法,第一个期望保存在一个变量中,因此如果需要可以从另一个函数中实现,另一个是在函数体中本地创建并从闭包中实现。

【讨论】:

以上是关于在 XCTestCase 的 setUp() 中等待多个异步调用的主要内容,如果未能解决你的问题,请参考以下文章

XCTestCase 使用异步操作设置一次

如何在静态 objc 库中使用 XCTestcase

XCTestCase 异步

如何在 XCTestCase 中禁用“所有异常”

如何在 XCTestCase 中测试 NSPersistentDocument?

XCTestCase 不提供项目类