Testing with async/await
Not long time ago I began journey transitioning from traditional imperative programming to functional way. Advantage of the functional programming is less code and less mutable states. It involved refactoring, and because I have limited time, I thought that adding unit tests will help me in maintaining my projects. I will write about my journey and lessons I learned as it helps me and hopefully will help you, dear reader.
One of problems I faced is with initialising my data model.
View model values are not populated at the time of assertion because I use main thread dispatcher in my implementation of the loadViewModel
function.
func loadViewModel() {
Task {
let appModel = self.pinbookModel
await MainActor.run {
self.viewModel = appModel
}
}
}
Remember await
keyword is not blocking and assertion runs before pins
and tags
are populated.
I have started to notice the test passing sometimes with await task.value
additional line:
func testAddPin() async {
let database = self.newTestDatabase()
let task = Task {
await database.loadViewModel()
}
await task.value
let pins = await database.viewModel.pins
let tags = await database.viewModel.tags
XCTAssertEqual(pins.count, 3)
XCTAssertEqual(tags.count, 2)
}
Above passing for me only sometimes, not acceptable. I had to do more changes so the test now passes every time I run it.
func testAddPin() {
let database = self.newTestDatabase()
let task = Task {
await database.loadViewModel()
}
Task {
await task.value
let pins = await database.viewModel.pins
let tags = await database.viewModel.tags
XCTAssertEqual(pins.count, 3)
XCTAssertEqual(tags.count, 2)
}
}
If you need more guidance writing your first async/await project and you not sure how to structure your code. I recommend this sample project from Apple: CloudKit Samples: CKSyncEngine.