Swift测试目标内private类静态方法可访问问题咨询
问题原因
不存在测试目标独有的访问控制特殊规则,你遇到的差异和是否继承XCTestCase没有直接关系,本质是Swift private 访问级别的原生规则,加上两边编译配置、代码修饰符的细微区别导致的。
先纠正对Swift private的认知偏差
Swift的private不是“只有类型自身能访问”的严格权限,具体规则如下:
- 嵌套在类型/结构体等内部的非顶级
private实体:仅能在直接包围它的声明作用域,以及同文件内该声明的扩展中访问 - 写在文件顶级的
private实体:默认和fileprivate权限一致,允许同文件内的所有代码访问,只有两种情况会报不可访问的错误:- 在
public/open修饰的类型内部引用这个private顶级实体:public类型的实现逻辑不允许引用访问级别差过大的private实体 - 编译时开启了
BUILD_LIBRARY_FOR_DISTRIBUTION(库演进支持,一般开发SDK、发版Swift Package时会开启):此时顶级private的访问范围会被严格收窄,同文件的其他顶级类型也不能访问
- 在
两边表现不一致的具体原因
- 测试目标中能正常调用:
测试目标默认关闭BUILD_LIBRARY_FOR_DISTRIBUTION,你的MyClass作为XCTestCase子类没有显式写public/open修饰符,默认访问级别是internal,完全符合同文件访问顶级private实体的要求,所以编译运行都正常。你可以做个简单验证:把测试目标里的MyClass改成public class MyClass: XCTestCase,再调用MyHelper的方法,一样会抛出不可访问的错误。 - 移到主目标就报错:
要么是你移动代码时不小心给MyClass加了public/open修饰符,或者把MyHelper放到了其他类型的作用域内部;要么是你的主目标开启了BUILD_LIBRARY_FOR_DISTRIBUTION(比如主目标是动态库、Swift Package,或者手动开了这个编译选项),触发了private的访问限制,和你删不删XCTestCase继承关系没有关联。
你可以在主目标里关闭BUILD_LIBRARY_FOR_DISTRIBUTION,保持MyClass为默认的internal级别、和MyHelper同属顶级作用域,此时一样可以正常调用MyHelper的方法,和测试目标的表现没有区别。
内容的提问来源于stack exchange,提问作者Sean
相关产品推荐
相关产品推荐

