Using Dispatch.main in code called from XCTestCase does not work

 ̄綄美尐妖づ 提交于 2021-02-08 08:35:38

问题


I have a function that is a async wrapper around a synchronous function.

The synchronous function is like:

class Foo {
    class func bar() -> [Int] {
        return [1,2,3]
    }

    class func asyncBar(completion: @escaping ([Int]) -> Void) {
        DispatchQueue.global(qos: .userInitiated).async {
            let intArray = bar()
            DispatchQueue.main.async {
                completion(intArray)
            }
        }
    }
}

When I call it from a XCTestCase completion does not run.

Is there some sort of perverse interaction between the way unit tests are done in XCode and the main thread?

I can find no documentation on the Web about this.

I have to use the main thread for the callback as it interacts with the Gui.

My test case looks something like:

func testAsyncBar() throws {
    var run = true
    func stopThisThing(ints: [Int]) {
        run = false
    }
    Foo.asyncBar(completion: stopThisThing)
    while run {
        print ("Running...")
        usleep(100000)
    }
}

The busy loop at the end never stops.


回答1:


Your test’s while loop will block the main thread (if the test runs on the main thread). As such, the closure dispatched via DispatchQueue.main.async can never run, and your run Boolean will never get reset. This results in a deadlock. You can confirm this by printing Thread.isMainThread or adding a test like dispatchPrecondition(condition: .onQueue(.main)).

Fortunately, unit tests have a simple mechanism that avoids this deadlock. If you want unit test to wait for some asynchronous process, use an XCTestExpectation:

func testAsyncBar() throws {
    let e = expectation(description: "asyncBar")

    func stopThisThing(ints: [Int]) {
        e.fulfill()
    }

    Foo.asyncBar(completion: stopThisThing)

    waitForExpectations(timeout: 5)
}

This avoids problems introduced by the while loop that otherwise blocked the thread.

See Testing Asynchronous Operations with Expectations.



来源:https://stackoverflow.com/questions/65572514/using-dispatch-main-in-code-called-from-xctestcase-does-not-work

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!