我正在为public method编写BDD单元测试.该方法更改了一个私有属性(private var),因此我想编写一个expect(),并确保它设置正确.由于它是私有的,我无法确定如何从单元测试目标访问它.

对于Objective-C,我只需要添加一个扩展标题.Swift 有类似的技巧吗?值得注意的是,该属性还有一个didSet()和一些代码.

推荐答案

(请注意,Swift 2添加了@testable属性,可以使内部方法和属性可用于测试.有关更多信息,请参阅下面的@JeremyP注释.)

不,在Swift ,隐私就是隐私.编译器可以使用这一事实进行优化,因此,根据您使用该属性的方式,编译器删除、内联该属性,或者根据该文件中的实际代码执行任何其他操作都是合法的.(无论优化器现在是否真的那么智能,它都是允许的.)

当然,如果你宣布你的类是@objc,那么你可以打破那些优化,你可以用ObjC来阅读它.还有一些奇怪的变通方法,可以让你使用Swift调用任意@objc个公开的方法(比如零超时NSTimer).但不要那样做.

这是一个classic 的测试问题,classic 的测试答案是不要以这种方式测试.不要测试内部状态.如果真的无法从外部判断出发生了什么,那么就没有什么可测试的了.重新设计对象,使其可在其公共接口上进行测试.通常这意味着作曲和模仿.

这个问题最常见的版本可能是缓存.很难测试是否缓存了某些内容,因为唯一的区别可能是检索速度更快.但它仍然可以测试.将缓存功能移动到另一个对象中,并让您的测试对象接受自定义缓存对象.然后可以传递一个模拟,记录是否进行了正确的缓存调用(或网络调用、数据库调用,或任何内部状态).

基本上,答案是:重新设计,以便更容易测试.

好吧,但你真的,真的,真的需要它...怎么做?好吧,在不 destruct 世界的情况下这是可能的.

在要测试的文件中创建一个函数,公开你想要的东西.不是一种方法.只是一个自由函数.然后你可以把助手函数放在#if TEST中,并在测试配置中设置TEST.理想情况下,我会让函数真正测试你关心的事情,而不是expose 变量(在这种情况下,也许你可以让函数内部甚至公开).但不管怎样.

Swift相关问答推荐

SwiftUI状态更新

对多个项目的数组进行排序

";async let和";async之间的差异让我们等待";

如何在visionOS上删除PhotosPicker背景 colored颜色 ?

在SwiftUI中使用自定义图像填充列表行的正确方法

OBJC代码中Swift 演员的伊瓦尔:原子还是非原子?

格式化单位和度量值.为什么从符号初始化的单位不能产生与静态初始化相同的结果

如何才能在同一线程上调用类中的每个方法,而不对每个调用使用同步块?

是否可以将具有关联值的枚举强制转换为其类型与关联值匹配的变量?

如何在 Vapor 中制作可选的查询过滤器

避免 `(())` 显式指定 Void 类型的枚举关联值

如何在 macOS/AppKit 的窗口选项卡上接受拖动项目的放置?

Swiftui 无法从核心数据中获取数据

如何延迟 swift 属性 didSet 使其每秒只触发一次

使用 RxSwift 围绕 async/await 方法创建 Observable

`let case(value)` 和 `case(let value)` 之间的区别 (Swift)

不要从 NumberFormatter 获取货币符号

获取 SwiftUI 中 Binding 的值更改更新

FirebaseStorage:如何删除目录

如何判断 firebase 数据库值是否存在?