如何测试Swift的异步方法

sna*_*ggs 4 swift

我有以下要从联合运行的课程:

class WmBuildGroupsTask{

init(){}

    func doInBackground() -> WmTransferItem{
         NSThread.sleepForTimeInterval(20)// sleep 20 sec to simulate long task
                            }

    func onPostExecute(transferItem:WmTransferItem){        
        //called when long task finished        
    }


    func execute(){        
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {

            var  transItem:WmTransferItem = self.doInBackground()

            dispatch_async(dispatch_get_main_queue(), {
                self.onPostExecute(transItem)
                });
            });                
      }    
}
Run Code Online (Sandbox Code Playgroud)

我试图从Unitest文件运行:

var task:WmBuildGroupsTask = WmBuildGroupsTask()
task.execute(); 
Run Code Online (Sandbox Code Playgroud)

但测试在doInBackground()方法完成之前完成.

如何使它工作?

Max*_*tin 12

您可以通过使用XCTestExpectation(从Xcode 6开始)实现这一目标.

这个怎么运作:

我们创建XCTestExpectation像计时器一样工作的实例.在两种情况之一发生之前​​,您的测试永远不会完成:

  • XCTestExpectation.fulfill()
  • 你定义了超时waitForExpectationsWithTimeout,因此测试将失败

如何使用 XCTestExpectation

步骤1

为被测试的类创建新协议(在您的情况下WmBuildGroupsTask):

protocol MyCallback{
    func onDone(results: String)
}
Run Code Online (Sandbox Code Playgroud)

这是我们的回调.

第2步

在Unitest中继承了这个协议:

class Test_WmBuildGroupsTask : XCTestCase, MyCallback {
/* ...*/    
}
Run Code Online (Sandbox Code Playgroud)

第3步

创建XCTestExpectation变量(in Test_WmBuildGroupsTask):

var theExpectation:XCTestExpectation?
Run Code Online (Sandbox Code Playgroud)

并启动onDone()方法:

func onDone(results: String){

    theExpectation?.fulfill() // it will release our "timer"
}
Run Code Online (Sandbox Code Playgroud)

第4步

我们的测试示例:

func test___WmBuildGroupsTask() {

    // Declare  expectation
     theExpectation = expectationWithDescription("initialized") // dummy text

    var task:WmBuildGroupsTask = WmBuildGroupsTask()
    task.delegate = self // pass delegate to WmBuildGroupsTask class        
    task.execute();


    // Loop until the expectation is fulfilled in onDone method
    waitForExpectationsWithTimeout(500, { error in XCTAssertNil(error, "Oh, we got timeout")
    })
}// end func
Run Code Online (Sandbox Code Playgroud)

那么现在我们要做的就是添加一些东西WmBuildGroupsTask:

第5步

添加新变量:

var delegate:MyCallback?
Run Code Online (Sandbox Code Playgroud)

改变onPostExecute方法:

func onPostExecute(transferItem:WmTransferItem){
   /* .. */

   delegate?.onDone("finished")// call callback        
}
Run Code Online (Sandbox Code Playgroud)

就这样.

(经测试)