Swift - 涉及IBOutlets的单元测试功能?

时间:2014-11-04 17:06:56

标签: unit-testing swift iboutlet

我正在为我的Swift项目设置单元测试,并且无法测试涉及更新IBOutlets的类函数。

我有一个函数validateUrl,它希望传递一个字符串,然后验证它。如果它有效,则启用UIButton,如果它无效,则禁用UIButton。当我运行调用此函数的测试时,应用程序在启用或禁用UIButton的代码行上崩溃。 故事板和控制器都具有适当的测试目标集。

这行代码:

    self.submitButton.enabled = true// Enable Submit Button

吐出此错误:

fatal error: unexpectedly found nil while unwrapping an Optional value

6 个答案:

答案 0 :(得分:8)

您必须使用故事板启动视图控制器。请参阅此处的文档:https://developer.apple.com/library/ios/documentation/uikit/reference/UIStoryboard_Class/index.html#//apple_ref/occ/instm/UIStoryboard/instantiateViewControllerWithIdentifier

如果直接初始化视图控制器,它将没有任何连接,因为在这种情况下VC本身不知道故事板。

答案 1 :(得分:6)

尝试使用此代码初始化视图控制器的IbOutlets:

   let yourStoryboard = UIStoryboard(name: "Your_storyboard", bundle: nil)
   yourViewController = yourStoryboard.instantiateViewController(withIdentifier: "YourViewController") as! YourViewController
   yourViewController.loadView() // This line is the key

答案 2 :(得分:2)

您可能需要在测试之前将控制器视图添加到层​​次结构以强制控制器加载XIB

let localContainer = UIView(frame:someFrame)
let controllerUnderTest = //instantiate your controller
localContainer.addSubview(controllerUnderTest.view)

//at this point you can test outlets

否则您的网点将为零,因为它们尚未连接。

答案 3 :(得分:1)

我用来测试Swift中的类的解决方案是在测试的setUp()方法中创建出口。例如,我有一个UIViewController子类,它有一个UIImageView作为插座。我声明我的View控制器子类的一个实例是我的测试类的属性,&通过初始化一个新的UIImageView在setUp()方法中配置它的出口。

var viewController = ViewController() // property on the test class

override func setUp() {
    super.setUp()
    viewController.imageView = UIImageView(image: UIImage(named: "Logo")) // create a new UIImageView and set it as the outlet object
}

任何其他出口都可以类似地在setUp方法中设置,这样你甚至不必实例化故事板(出于某种原因,尽管我能够实例化一个UIStoryboard对象我的测试,视图控制器出口仍然没有。)

答案 4 :(得分:0)

@talzag在您的情况下,iboutlet为零,因为它们是弱变量,应该在实例化后立即取消分配。

答案 5 :(得分:0)

测试IBOutlet并不是最好的方法,因为:

  • 插座应被视为实施细节,并应声明为私有
  • 插座通常与纯UI组件连接,而单元测试则用于测试业务逻辑
  • 通过另一种功能测试注入到插座中的值可以看作是集成测试。通过测试已连接/未连接的插座方案,您还将使必须编写的单元测试加倍。

在您的特定情况下,我建议改为测试验证器功能,但首先使其独立于控制器类(如果尚未使用)。将该功能用作输入/输出功能还带来了其他好处,例如提高了可重用性。

测试了验证程序的所有可能情况之后,验证插座是否正常运行,只需进行快速手动测试即可:只需检查插座的行为是否类似于返回的验证程序。 UI内容更适合进行手动测试,因为手动测试也可以捕获其他细节(例如位置,颜色等)。

但是,如果您真的想测试出口行为,那么一种属于单元测试原理的技术就是快照测试。有一些可用的库,我推荐https://github.com/uber/ios-snapshot-test-case/中的库。