I have following class that I want to run from unites:
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)
});
});
}
}
I tried to run from Unitest file:
var task:WmBuildGroupsTask = WmBuildGroupsTask()
task.execute();
but test is done before doInBackground()
method finished.
How to make it work?
You can achieve that by using XCTestExpectation
(since Xcode 6).
How it works:
We create XCTestExpectation
instance that work like timer. Your test will never finish till one of both cases happend:
XCTestExpectation.fulfill()
calledwaitForExpectationsWithTimeout
and therefore test will failXCTestExpectation
Step 1
Create new protocol for class under test (in your case WmBuildGroupsTask
):
protocol MyCallback{
func onDone(results: String)
}
This is our callback.
Step 2
in Unitest inherit this protocol:
class Test_WmBuildGroupsTask : XCTestCase, MyCallback {
/* ...*/
}
Step 3
create XCTestExpectation
variable (in Test_WmBuildGroupsTask
):
var theExpectation:XCTestExpectation?
and initiate onDone()
method:
func onDone(results: String){
theExpectation?.fulfill() // it will release our "timer"
}
Step 4
Example of our test:
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
So now what left us to do is to add some stuff to WmBuildGroupsTask
:
Step 5
add new variable:
var delegate:MyCallback?
change onPostExecute
method to:
func onPostExecute(transferItem:WmTransferItem){
/* .. */
delegate?.onDone("finished")// call callback
}
Thats all.
( Tested )
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With