首页
/ Swift-Testing 项目中异步测试的注意事项

Swift-Testing 项目中异步测试的注意事项

2025-07-06 20:59:45作者:范垣楠Rhoda

在 Swift 测试开发中,使用 async/await 进行异步测试是一种常见的需求。最近在 swift-testing 项目中发现了一个关于异步测试宏使用的常见误区,值得开发者们注意。

问题背景

当开发者尝试使用 #expect(throws:) 宏来测试一个会抛出错误的异步方法时,可能会遇到编译器报错"async call in a function that does not support concurrency"。这种情况通常发生在测试函数本身没有标记为 async 的情况下。

正确用法

要正确测试异步抛出方法,测试函数本身必须标记为 async,并且在调用 #expect(throws:) 宏时需要使用 await 关键字。这是因为:

  1. 宏声明本身不能包含效果说明(effect specifiers),也就是说不能像函数那样直接声明 macro expect(...) async throws
  2. 当宏的闭包体是 async 时,调用站点也必须是异步的

正确的写法应该是:

@Test func throwErrorIfAccountBalanceIsLessThan1000() async {
    let bankAccount = BankAccount(balance: 250, accountHolder: "John Doe", accountNumber: "987654", ssn: "345-23-3212")
    
    let mockedCreditScoreService = CreditScoreServiceMock(creditScore: 700)
    let loanService = LoanService(creditScoreService: mockedCreditScoreService)
    
    await #expect(throws: LoanServiceError.self, performing: {
        try await loanService.applyForLoan(bankAccount: bankAccount, amount: 5000)
    })
}

技术原理

Swift 的宏系统目前有一些限制,特别是关于效果说明方面。由于宏不能直接声明为 asyncthrows,因此当宏内部使用异步或抛出操作时,这些效果必须由调用站点来处理。

在测试场景中,这意味着:

  1. 如果测试的代码是异步的,测试函数必须标记为 async
  2. 如果测试的代码会抛出错误,测试函数应该能够处理这些错误
  3. 当使用 #expect(throws:) 测试异步抛出方法时,需要同时使用 awaittry(如果需要)

最佳实践

  1. 始终检查测试函数是否具有正确的效果说明(async/throws
  2. 当测试异步代码时,确保测试函数标记为 async
  3. 使用 #expect(throws:) 测试异步抛出方法时,记得添加 await 关键字
  4. 考虑为复杂的异步测试场景编写辅助函数,减少重复代码

总结

Swift 测试中的异步操作需要特别注意函数声明和调用方式。理解宏系统的限制和异步测试的正确写法,可以帮助开发者避免常见的编译错误,编写出更加健壮的测试代码。记住,当测试异步代码时,测试函数本身也必须是异步的,这是 Swift 并发模型的基本要求。

登录后查看全文
热门项目推荐
相关项目推荐