Testing the content of a `Task` in a non-async method

Hi,

Considering this method I'd like to test:

public func play(_ soundFileName: String, shouldLoop: Bool) {
        Task {
            await dataSource.play(soundFileName, shouldLoop: shouldLoop)
        }
    }

Previously, with XCTest we could use an expectation and wait for it to be fulfilled:

func test() 
sut.play("", shouldLoop: false)
wait(for: [mockedAudioPlayerDataSource.invokedPlayExpectation])
XCTAssertEqual(mockedAudioPlayerDataSource.invokedPlayCount, 1)

With Swift Testing, I am unsure what a unit test looks like.

Answered by DTS Engineer in 810603022

You code doesn’t include all the details necessary to see exactly what you’re trying to do here, and that make it hard to offer a definitive answer. However, in general, Swift Testing does allow you to test asynchronous code via the Confirmation type. See Testing asynchronous code.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

You should make your play function async, then use Swift Async to make sure assertion runs after sound played.

public func play(_ soundFileName: String, shouldLoop: Bool) async {
    await dataSource.play(soundFileName, shouldLoop: shouldLoop)
}
Task {
    await play("", shouldLoop: false)
    #expect(mockedAudioPlayerDataSource.invokedPlayCount == 1)
}


WindowsMEMZ @ Darock Studio
let myEmail = "memz" + "1" + "@" + "darock.top"

Unfortunately, this isn't always possible. Sometimes, as an intermediate step, we don't want to make this change because it can propagate to the rest of the code base. How should we handle these types of situations?

You code doesn’t include all the details necessary to see exactly what you’re trying to do here, and that make it hard to offer a definitive answer. However, in general, Swift Testing does allow you to test asynchronous code via the Confirmation type. See Testing asynchronous code.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

You can also use a wrapper like this:

public func _play(_ soundFileName: String, shouldLoop: Bool) async {
    await dataSource.play(soundFileName, shouldLoop: shouldLoop)
}

public func play(_ soundFileName: String, shouldLoop: Bool) {
    Task {
        await _play(soundFileName, shouldLoop: shouldLoop)
    }
}

Then use play in your code and _play for testing.


WindowsMEMZ @ Darock Studio
let myEmail = "memz" + "1" + "@" + "darock.top"

Testing the content of a `Task` in a non-async method
 
 
Q