Home > OS >  Swift how to test async call wrapped in a function
Swift how to test async call wrapped in a function

Time:06-15

Is there a way to wait for an async call to be finished when this call is wrapped in another method?

class Owner{
   let dataManager = MockDataManager()
   var data: String? = nil

   func refresh() {
        Task {
            self.data = await dataManager.fetchData()
        }
    }
}

class MockDataManager {
    var testData: String = "test"
    func fetchData() async -> String {
       testData
    }
}

class OwnerTests: SKTestCase {
    private var owner = Owner()
    
    func testRefresh() {
        owner.refresh()
        XCTAssertEqual(owner.data, "test") // fail. the value is still nil
    }
}

With callbacks, the tests used to work if everything under the hood was replaced with synchronous calls but here it looks like i am missing an operation to wait for a change to owner.data

CodePudding user response:

func refresh() async {
    self.data = await dataManager.fetchData()
}

then in the test await owner.refresh()

If you really need to wait synchronously for the async task, you can see this question Swift await/async - how to wait synchronously for an async task to complete?

CodePudding user response:

You can use an XCTestExpectation and wait for the exception to be fulfilled. In the below example I am waiting 1 second

func test_Refresh() {
    let owner = Owner()
    let expectation = XCTestExpectation()

    owner.refresh()
    expectation.fulfill()

    wait(for: [expectation], timeout: 1)
    XCTAssertEqual(owner.data, "test")
}
  • Related