Bartłomiej Semańczyk
Bartłomiej Semańczyk

Reputation: 61880

How to test method that runs async on main thread?

I simply have a method:

func update(with process: PresentableProcess) {
    presentableProcess = process
    if isViewLoaded {
        DispatchQueue.main.async { [weak self] in
            //do something on the main thread
        }
    }
}

And its test:

func testPreferredContentSizeWhenTitleExist() {
    let process = PresentableProcess(title: "title")
    sut.update(with: process)

    XCTAssertEqualWithAccuracy(sut.preferredContentSize, 95, accuracy: 10)
}

It doesn't work, because it runs on the main thread. I would like to avoid adding completion block in update(with) to pass a test.

Upvotes: 1

Views: 2664

Answers (2)

Maxime
Maxime

Reputation: 1392

Your method must have a completion block. Then you can use an Expectation object

let urlExpectation = expectation(description: "GET \(url)")
let process = PresentableProcess(title: "title")
sut.update(with: process) {
    XCTAssertEqualWithAccuracy(sut.preferredContentSize, 95, accuracy: 10)
    urlExpectation.fulfill()
}

Or to avoid adding the completion block, you can create a protocol with a method called when setup is ended.

Upvotes: 0

mag_zbc
mag_zbc

Reputation: 6992

I'm afraid you will need to use completion block. To test asynchronous functions use expectations

let expectation = expectation(description: "expectation")

doStuffWithCompletion() {
    expectation.fulfill()
}

waitForExpectations(timeout: 10) { error in
    //
}

Upvotes: 1

Related Questions