我正在为public method编写BDD单元测试.该方法更改了一个私有属性(private var
),因此我想编写一个expect(),并确保它设置正确.由于它是私有的,我无法确定如何从单元测试目标访问它.
对于Objective-C,我只需要添加一个扩展标题.Swift 有类似的技巧吗?值得注意的是,该属性还有一个didSet()和一些代码.
我正在为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 变量(在这种情况下,也许你可以让函数内部甚至公开).但不管怎样.