为UIViewControllerRepresentable写单元测试遇Context初始化错误
解决UIViewControllerRepresentableContext无法初始化的测试问题
你遇到的错误是因为UIViewControllerRepresentableContext的初始化器是SwiftUI内部实现,对外不可访问,无法直接在测试代码中实例化。以下是两种可行的解决方案:
方案1:抽离核心逻辑到可测试方法
将makeUIViewController中创建和配置视图控制器的逻辑抽成独立方法,绕过对上下文的依赖,直接测试核心逻辑:
修改DocumentPicker结构体
struct DocumentPicker: UIViewControllerRepresentable { class Coordinator: NSObject, UIDocumentPickerDelegate { var parent: DocumentPicker init(parent: DocumentPicker) { self.parent = parent } func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) { parent.didPickDocuments(urls) } func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) { parent.didCancel() } } var didPickDocuments: ([URL]) -> Void var didCancel: () -> Void func makeCoordinator() -> Coordinator { Coordinator(parent: self) } func makeUIViewController(context: Context) -> UIDocumentPickerViewController { makePicker(with: context.coordinator) } // 抽离的方法,直接接收协调器参数 func makePicker(with coordinator: Coordinator) -> UIDocumentPickerViewController { let picker = UIDocumentPickerViewController(forOpeningContentTypes: [.item], asCopy: true) picker.delegate = coordinator picker.allowsMultipleSelection = true return picker } func updateUIViewController(_ uiViewController: UIDocumentPickerViewController, context: Context) {} }
修改测试用例
class DocumentPickerCreationTests: XCTestCase { func testMakeCoordinator() { let documentPicker = DocumentPicker(didPickDocuments: { _ in }, didCancel: { }) let coordinator = documentPicker.makeCoordinator() XCTAssertNotNil(coordinator) XCTAssertTrue(coordinator is DocumentPicker.Coordinator) } func testMakeUIViewController() { let documentPicker = DocumentPicker(didPickDocuments: { _ in }, didCancel: { }) let coordinator = documentPicker.makeCoordinator() // 直接调用抽离的方法,无需创建上下文 let viewController = documentPicker.makePicker(with: coordinator) XCTAssertTrue(viewController is UIDocumentPickerViewController) XCTAssertEqual(viewController.delegate as? DocumentPicker.Coordinator, coordinator) XCTAssertTrue(viewController.allowsMultipleSelection) } }
方案2:测试目标中扩展上下文初始化器
如果不想修改原业务代码,可以在测试文件中给UIViewControllerRepresentableContext添加测试专用的初始化器,需要先导入你的App模块并启用测试访问:
@testable import YourAppModule extension UIViewControllerRepresentableContext where Coordinator == DocumentPicker.Coordinator { // 自定义初始化器,使用默认环境和事务值 init(coordinator: Coordinator) { self.init(coordinator: coordinator, environment: EnvironmentValues(), transaction: Transaction()) } }
添加这个扩展后,你原来的测试代码就可以正常运行,无需其他修改。
内容的提问来源于stack exchange,提问作者Viral Shah
相关产品推荐
相关产品推荐

