Controlling time with async await in Swift

Viewed 102

Up to now I've been using Combine and the PointFree TestSchedulers https://github.com/pointfreeco/combine-schedulers to "control time" in my tests.

I can make a request and then assert values at certain points in the process without any trouble.

Example...

func testFetchContentSuccess() {
    let queue = TestSchedulerOf<DispatchQueue>(now: .init(.now()))

    let sut = sut(queue: queue.eraseToAnyScheduler())

    XCTAssertEqual(sut.content, .notAsked)

    sut.fetchContent()

    XCTAssertEqual(sut.content, .loading) // this would be impossible without a TestScheulder as the mock endpoint would return immediately.

    queue.advance() // this is what I'm looking for from async await

    assertSnapshot(matching: sut.content, as: .dump)
}

Is there a way to do something similar with async await?

1 Answers

Yes, and it's awesome!

You can just declare test methods as async, then await right in the test method.

So if this test is really about the results of the fetch, it could just be:

func testFetchContentSuccess() {
    let sut = ContentFetcher()

    XCTAssertEqual(sut.content, .notAsked)

    await sut.fetchContent()

    assertSnapshot(matching: sut.content, as: .dump)
}

I have lots of tests that use XCTestExpectation, and most get a lot shorter and easier to read when they're converted to be async/await based.

Related