如何在Swift单元测试中Mock依赖的Objective-C类?
解决OC类隐式遵守Swift协议的简单方案
核心思路:用Swift扩展让OC类无需修改源码即可遵守协议
你不需要修改Objective-C的ObjcClass源码,也不用放弃类型安全或使用复杂的类型擦除,只需要两步就能解决问题:
确保协议是
@objc修饰的
你的ObjcClassProtocol必须添加@objc关键字,才能和Objective-C类型交互,同时协议内的方法/属性签名要和ObjcClass的实现完全匹配:@objc protocol ObjcClassProtocol { // 匹配ObjcClass里的属性 @objc var targetProperty: NSString { get set } // 匹配ObjcClass里的方法(注意Swift到OC的方法名映射) @objc func executeTask(with input: NSInteger) -> Bool }给ObjcClass添加空扩展声明遵守协议
在Swift代码中,为ObjcClass写一个空扩展,直接声明它遵守ObjcClassProtocol:extension ObjcClass: ObjcClassProtocol {}因为
ObjcClass本身已经实现了协议要求的所有成员,这个扩展不需要写任何实现代码,只是告诉Swift编译器该类符合协议规范。
为什么这个方案可行?
Swift允许为已存在的Objective-C类扩展协议一致性,只要协议是@objc兼容的,且OC类的方法/属性签名和协议要求完全匹配,就可以通过这种"空扩展"的方式完成协议绑定,完全不需要修改OC源码,完美解决你提到的项目结构限制问题。
注意事项
- 协议必须用
@objc修饰,否则Swift无法将协议和OC类关联; - 协议内的成员签名必须和OC类的实现严格对应(比如OC的
- (void)doSomething;对应Swift协议里的@objc func doSomething()); - 如果OC类的方法有可选参数或特殊命名,要注意Swift和OC的方法名转换规则(比如OC的
- (void)handleItem:(id)item withOption:(BOOL)option对应Swift的@objc func handleItem(_ item: Any, withOption option: Bool))。
内容的提问来源于stack exchange,提问作者Cassiterite
相关产品推荐
相关产品推荐

