单元测试中如何获取传递给变量类型Completion Handler的值?
如何捕获变量式Completion Handler的返回值用于单元测试
我来帮你搞定这个单元测试里捕获onCompletion参数的问题!你这里把Completion Handler做成了实例变量onCompletion,确实和常规闭包传参的场景不太一样,但测试起来其实很简单,核心思路就是用一个测试专用的闭包替换掉原有的onCompletion,在闭包内部把收到的ResultType值存下来,之后就能轻松断言校验了。
具体实现步骤(基于XCTest)
首先我们需要在测试类里准备一个变量来存储捕获到的结果,然后替换目标对象的onCompletion为我们的测试闭包,最后调用目标方法并断言结果:
import XCTest @testable import YourAppModule // 替换成你的实际模块名 // 假设你的网络类叫NetworkManager,请替换成实际类名 class NetworkManagerTests: XCTestCase { var testNetworkManager: NetworkManager! // 用来存储捕获到的Completion结果 var capturedResult: ResultType? override func setUp() { super.setUp() // 初始化测试对象 testNetworkManager = NetworkManager() // 替换onCompletion为测试用闭包,捕获传入的Result testNetworkManager.onCompletion = { [weak self] result in self?.capturedResult = result } } override func tearDown() { // 测试后清空变量,避免影响其他测试用例 capturedResult = nil testNetworkManager = nil super.tearDown() } func testFinishedWithErrorsReturnsNetworkNotReachableError() { // 调用你要测试的finished方法,传入测试用错误 let testErrors = [NSError(domain: "TestErrorDomain", code: 999, userInfo: nil)] testNetworkManager.finished(testErrors) // 开始断言校验 XCTAssertNotNil(capturedResult, "Completion handler should have been triggered") // 校验结果是否为预期的failure类型 guard case .failure(let error) = capturedResult else { XCTFail("Expected a failure result but got success") return } // 进一步校验错误的具体类型 guard let eComError = error as? EComError, case .networkError(.notReachable) = eComError else { XCTFail("Expected EComError.networkError(.notReachable) but got \(error)") return } } }
注意事项
- 弱引用self:测试闭包里用
[weak self]是为了避免测试类和测试对象之间的循环引用,虽然测试用例的生命周期很短,但养成这个习惯能避免潜在的内存问题。 - 异步场景处理:如果你的
onCompletion是异步触发的(比如网络请求真正完成后才调用),那需要用XCTestExpectation来等待结果,示例如下:
func testAsyncNetworkCallReturnsResult() { let completionExpectation = expectation(description: "Wait for async completion") testNetworkManager.onCompletion = { [weak self] result in self?.capturedResult = result completionExpectation.fulfill() // 标记等待完成 } // 触发异步网络操作 testNetworkManager.startAsyncNetworkRequest() // 等待最多5秒,超时则测试失败 waitForExpectations(timeout: 5, handler: nil) // 之后对capturedResult进行断言,逻辑和同步场景一致 XCTAssertNotNil(capturedResult) // ...其他断言 }
内容的提问来源于stack exchange,提问作者SwiftyJD
相关产品推荐
相关产品推荐

