You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

跨包闭包抛出的Error未被Catch捕获,仅测试环境复现求助

问题:跨包定义的Error在测试环境中无法被正确捕获?

我正在测试函数中抛出的错误是否能被正确捕获,核心代码如下:

Package A 中的错误定义

public enum SomeError: Int, Error {
    case errorOne = 1
    case errorTwo = 2
}

Package B 中的业务代码

struct SomeStruct {
    let service: SomeService

    func functionThatShouldCatch() throws -> String {
        do {
            let result = try service.getSomething()
        } catch SomeError.errorOne {
            // 预期在此处捕获错误
        }
    
        return "All ok"
    }
}

Mock 服务类

class MockService: Service {
    var getSomethingHandler: (() throws -> String)? = nil
}

测试代码

@Test func testingAllOk() throws {
    mockService.getSomethingHandler = { throw SomeError.errorOne }

    let result = try sut.functionThatShouldCatch() // <- 测试失败,此处捕获到了SomeError.errorOne

    #expect(result == "All ok")
}

我省略了无关代码,只保留核心内容。想请教是配置有误,还是这种在闭包中抛出外部包Error的方式本身就无法正常工作?

另外,当我修改SomeStruct的代码,添加一个通用的catch分支后:

func functionThatShouldCatch() throws -> String {
    do {
        let result = try service.getSomething()
    } catch SomeError.errorOne {
        // 预期在此处捕获错误
    } catch {
        print(error) // <- 输出内容为SomeError.errorOne
    }

    return "All ok"
}

通用分支能打印出SomeError.errorOne,但专门针对errorOne的分支还是没触发。

更新
我发现问题关键在于SomeError的定义位置:当SomeError和错误捕获代码在同一个包中时,测试能正常捕获错误;但放在单独的外部包时,测试就失败,重命名也没用。奇怪的是,应用运行时这个逻辑是正常的,只有测试环境会出问题。


解答

这种情况大概率是测试目标的依赖配置问题,而非语言本身的限制,可从以下几个方向排查:

  • 检查测试Target的依赖:确保测试Target正确引入Package A,且没有重复导入(比如同时引入源码和预编译框架),避免运行时错误实例的类型与捕获分支中的类型属于不同模块。
  • 给SomeError添加Equatable实现:Swift的Error协议默认不要求实现Equatable,跨包时可能因类型匹配逻辑缺失导致分支捕获失败,添加后可明确匹配规则:
public enum SomeError: Int, Error, Equatable {
    case errorOne = 1
    case errorTwo = 2
}
  • 显式指定模块名:在捕获分支中用模块名限定错误类型,比如catch PackageA.SomeError.errorOne,规避模块解析或命名冲突问题。
  • 对比类型一致性:在测试的通用catch分支中打印type(of: error)和SomeError.errorOne的类型,确认二者是否完全一致。

总结来说,应用运行正常但测试失败,通常是测试环境的依赖或模块解析逻辑与主应用不一致导致的,而非跨包抛出错误本身的问题。


内容的提问来源于stack exchange,提问作者Bob Voorneveld

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 22:55:12