单元测试和私有变量

时间:2015-04-20 12:12:51

标签: unit-testing swift bdd

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

对于Objective-C,我只需添加扩展标头。 Swift中有类似的技巧吗?作为注释,该属性还有一个带有一些代码的didSet()。

1 个答案:

答案 0 :(得分:47)

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

没有。在Swift,私人是私人的。编译器可以使用这个事实进行优化,因此根据您使用该属性的方式,编译器删除它,内联它或做任何其他根据实际代码中的代码提供正确行为的事情是合法的。文件。 (优化器今天是否真的那么聪明,它是允许的。)

现在当然如果你声明你的类是@objc,那么你可以打破这些优化,你可以用ObjC来阅读它。还有一些奇怪的变通办法可以让你使用Swift来调用任意@objc暴露的方法(比如零超时NSTimer)。但不要这样做。

这是一个经典的测试问题,经典的测试答案是不要以这种方式进行测试。不要测试内部状态。如果从外面无法告诉事情已经发生,那么就没有什么可以测试的了。重新设计对象,使其在其公共接口上可测试。通常这意味着构图和嘲笑。

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

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

好的,但你真的,真的,真的需要它......怎么做?好吧,这可能不会破坏世界。

在要测试的文件中创建一个公开所需内容的函数。不是一种方法。只是一个免费的功能。然后,您可以将该帮助函数放在#if TEST中,并在测试配置中设置TEST。理想情况下,我会让函数实际测试你关心的事情,而不是暴露变量(在这种情况下,也许你可以让函数在内部甚至公开)。但不管怎样。