Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I get XCTest to wait for async calls in setUp before tests are run?

I'm writing integration tests in Xcode 6 to go alongside my unit and functional tests. XCTest has a setUp() method that gets called before every test. Great!

It also has XCTestException's which let me write async tests. Also great!

However, I would like to populate my test database with test data before every test and setUp just starts executing tests before the async database call is done.

Is there a way to have setUp wait until my database is ready before it runs tests?

Here's an example of what I have do now. Since setUp returns before the database is done populating I have to duplicate a lot of test code every test:

func test_checkSomethingExists() {      let expectation = expectationWithDescription("")     var expected:DatabaseItem      // Fill out a database with data.      var data = getData()     overwriteDatabase(data, {       // Database populated.       // Do test... in this pseudocode I just check something...       db.retrieveDatabaseItem({ expected in          XCTAssertNotNil(expected)          expectation.fulfill()       })     })      waitForExpectationsWithTimeout(5.0) { (error) in         if error != nil {             XCTFail(error.localizedDescription)         }     }  } 

Here's what I would like:

class MyTestCase: XCTestCase {      override func setUp() {         super.setUp()          // Fill out a database with data. I can make this call do anything, here         // it returns a block.         var data = getData()         db.overwriteDatabase(data, onDone: () -> () {             // When database done, do something that causes setUp to end             // and start running tests          })             }      func test_checkSomethingExists() {          let expectation = expectationWithDescription("")         var expected:DatabaseItem             // Do test... in this pseudocode I just check something...           db.retrieveDatabaseItem({ expected in              XCTAssertNotNil(expected)              expectation.fulfill()         })          waitForExpectationsWithTimeout(5.0) { (error) in             if error != nil {                 XCTFail(error.localizedDescription)             }         }      }  } 
like image 679
Brett Elliot Avatar asked Apr 08 '15 02:04

Brett Elliot


People also ask

What is the test method to test an asynchronous operation in XCTest?

XCTest provides two approaches for testing asynchronous code. For Swift code that uses async and await for concurrency, you mark your test methods async or async throws to test asynchronously.

Which function can you use on XCTest to cleanup after every unit test?

Use these blocks to tear down state and clean up resources after a specific test method. XCTest runs the teardown methods once after each test method completes, with tearDown() first, then tearDownWithError() , then tearDown() async throws . Use these methods to tear down state after each test method.

Where will you use setUp () and tearDown () methods?

Prepare and Tear Down State for a Test Class XCTest runs setUp() once before the test class begins. If you need to clean up temporary files or capture any data that you want to analyze after the test class is complete, use the tearDown class method on XCTestCase .

Can tests be async?

It's common in JavaScript for code to run asynchronously. When you have code that runs asynchronously, Jest needs to know when the code it is testing has completed, before it can move on to another test.


1 Answers

Rather than using semaphores or blocking loops, you can use the same waitForExpectationsWithTimeout:handler: function you use in your async test cases.

// Swift override func setUp() {     super.setUp()      let exp = expectation(description: "\(#function)\(#line)")      // Issue an async request     let data = getData()     db.overwriteDatabase(data) {         // do some stuff         exp.fulfill()     }      // Wait for the async request to complete     waitForExpectations(timeout: 40, handler: nil) }  // Objective-C - (void)setUp {     [super setUp];      NSString *description = [NSString stringWithFormat:@"%s%d", __FUNCTION__, __LINE__];     XCTestExpectation *exp = [self expectationWithDescription:description];      // Issue an async request     NSData *data = [self getData];     [db overwriteDatabaseData: data block: ^(){         [exp fulfill];     }];              // Wait for the async request to complete     [self waitForExpectationsWithTimeout:40 handler: nil]; } 
like image 153
RndmTsk Avatar answered Oct 19 '22 23:10

RndmTsk