【问题标题】:Mark extension as @objc only for unit tests将扩展标记为 @objc 仅用于单元测试
【发布时间】:2019-08-29 18:10:15
【问题描述】:

我在目标 c 中声明了一个类,如下所示:

@interface Person : NSObject

@property (nonatomic, readonly) NSString* firstName;
@property (nonatomic, readonly) NSString* lastName;

@end

而且我在 Swift 中声明了一个扩展,以获得Person 的全名:

extension Person {
    var fullName: String {
      return "\(firstName) \(lastName)"
    } 
}

我想编写单元测试,我想在其中使用扩展名测试此人的全名。因此我创建了一个模拟子类,并覆盖了fullName 属性。但是,为了这样做,我必须使用 @objc 关键字将扩展暴露给目标 c 运行时。

有没有办法只为单元测试目标将扩展标记为@objc?标记扩展是否具有“显着”的编译/运行时影响?

我尝试添加一个 Swift 编译时间标志,例如:

#if UNIT_TEST_TARGET_RUNNING
@objc
#endif

但这会导致编译时错误。欢迎任何建议! 请注意,示例为了呈现问题而进行了简化,并且无法更改目标 c 接口。

【问题讨论】:

  • 我认为如果你在 #if 中使用 if else micro 声明变量两次,它会起作用,但我建议要么公开它,要么不公开它,不要让测试环境与真实环境不同案例,因为如果是这样,那么测试就没用了

标签: ios objective-c swift unit-testing


【解决方案1】:

标记扩展是否有“显着”的编译/运行时影响?

不是真的。编译器会生成一个 thunk,它是一个调用 Swift 方法的 Objective C 方法。这个 thunk 是在 ObjC 运行时注册的,它就是它所看到的。除其他外,它与 Swift 通用货币类型以及在 Object C 中使用的货币类型相互转换。

如果您想继承并覆盖该属性,请继续执行此操作。这真的没什么大不了的。

或者,您可以将类的接口提取到协议中,在“真实”实现中符合该协议,并创建一个模拟所有测试方法的测试替身。

【讨论】:

    猜你喜欢
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    相关资源
    最近更新 更多