首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法在XCTest中从UIStoryboard转换自定义UIViewController

无法在XCTest中从UIStoryboard转换自定义UIViewController
EN

Stack Overflow用户
提问于 2014-08-17 07:38:17
回答 3查看 14.8K关注 0票数 16

在Swift,Xcode6-Beta5中,我试图对我的"ViewController“进行单元测试,这不是一个很有创意的名字。

从其他响应来看,我认为我没有正确配置我的"Tests“目标。

失败的测试代码:

代码语言:javascript
复制
  func testItShouldLoadFromStoryboard() {

    var storyBoard: UIStoryboard?
    var anyVC: AnyObject?
    var viewController: ViewController?
    var uiViewController: UIViewController?

    storyBoard = UIStoryboard(name:"Main", bundle: nil)
    XCTAssert(storyBoard != nil, "Test Not Configured Properly")

    anyVC = storyBoard?.instantiateInitialViewController()
    viewController = anyVC  as? ViewController
    // Failing Assertion 
    XCTAssert(viewController != nil, "Test Not Configured Properly")

    uiViewController = anyVC as? UIViewController
    XCTAssert(uiViewController != nil, "Test Not Configured Properly")

  }

我可以用下面的几行代码来强制强制转换:

代码语言:javascript
复制
anyVC = storyBoard?.instantiateInitialViewController()
viewController = (anyVC != nil) ? (anyVC  as ViewController) : nil

但这导致了以下崩溃:

代码语言:javascript
复制
libswiftCore.dylib`swift_dynamicCastClassUnconditional:
0x10724f5a0:  pushq  %rbp
0x10724f5a1:  movq   %rsp, %rbp
0x10724f5a4:  pushq  %r14
0x10724f5a6:  pushq  %rbx
0x10724f5a7:  movq   %rsi, %rbx
0x10724f5aa:  movq   %rdi, %r14
0x10724f5ad:  testq  %r14, %r14
0x10724f5b0:  je     0x10724f5de               ; swift_dynamicCastClassUnconditional + 62
0x10724f5b2:  movabsq $-0x7fffffffffffffff, %rax
0x10724f5bc:  andq   %r14, %rax
0x10724f5bf:  jne    0x10724f5de               ; swift_dynamicCastClassUnconditional + 62
0x10724f5c1:  movq   %r14, %rdi
0x10724f5c4:  callq  0x107279a6e               ; symbol stub for: object_getClass
0x10724f5c9:  nopl   (%rax)
0x10724f5d0:  cmpq   %rbx, %rax
0x10724f5d3:  je     0x10724f5ed               ; swift_dynamicCastClassUnconditional + 77
0x10724f5d5:  movq   0x8(%rax), %rax
0x10724f5d9:  testq  %rax, %rax
0x10724f5dc:  jne    0x10724f5d0               ; swift_dynamicCastClassUnconditional + 48
0x10724f5de:  leaq   0x3364d(%rip), %rax       ; "Swift dynamic cast failed"
0x10724f5e5:  movq   %rax, 0xa456c(%rip)       ; gCRAnnotations + 8
0x10724f5ec:  int3   
0x10724f5ed:  movq   %r14, %rax
0x10724f5f0:  popq   %rbx
0x10724f5f1:  popq   %r14
0x10724f5f3:  popq   %rbp
0x10724f5f4:  retq   
0x10724f5f5:  nopw   %cs:(%rax,%rax)

我还成功地直接实例化了ViewController,但这不会进行IBOutlet处理,这是我测试的目的之一,以确保我不会通过重命名事物、删除Storyboard编辑器中的连接或我发现的许多其他破坏事物的方法来破坏链接……

编辑-我从一个全新的项目开始,选择iOS应用程序->单视图应用程序模板。

将testExample替换为如下所示的代码,将ViewController添加到测试目标。类似的结果。这个模板只有一个ViewController类型的视图控制器,在故事板中没有其他东西。

代码语言:javascript
复制
  func testExample() {


      var storyBoard: UIStoryboard?
      var anyVC: AnyObject?
      var viewController: ViewController?

      storyBoard = UIStoryboard(name:"Main", bundle: nil)
      XCTAssert(storyBoard != nil, "Test Not Configured Properly")

      anyVC = storyBoard?.instantiateInitialViewController()
      viewController = anyVC as? ViewController
      XCTAssert(viewController != nil, "Test Not Configured Properly")

      // This is an example of a functional test case.
      XCTAssert(true, "Pass")

    }

在设置了anyVC的值之后,在断点处输出以下lldb:

代码语言:javascript
复制
(lldb) po anyVC
(instance_type = Builtin.RawPointer = 0x00007fe22c92a290 -> 0x000000010e20bd80 (void *)0x000000010e20bea0: OBJC_METACLASS_$__TtC22TestingViewControllers14ViewController)
 {
  instance_type = 0x00007fe22c92a290 -> 0x000000010e20bd80 (void *)0x000000010e20bea0: OBJC_METACLASS_$__TtC22TestingViewControllers14ViewController
} 
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-08-20 02:52:31

我想出了一个比公开一切更好的解决方案。实际上,您只需要使用来自测试包的故事板,而不是使用nil (强制它来自主目标的包)。

代码语言:javascript
复制
var storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: NSBundle(forClass: self.dynamicType))
vc = storyboard.instantiateViewControllerWithIdentifier("LoginVC") as LoginViewController
vc.loadView()
票数 16
EN

Stack Overflow用户

发布于 2014-08-19 05:06:07

感谢@Derrik Hathaway提供的解决方案的关键。应用程序和测试目标是不同的模块。

我的应用程序使用了一个不合适的名称TestingViewControllers来纠正这个问题,我做了以下更改,并在应用程序代码中将ViewController设为public类。

将这一行添加到测试用例中:

代码语言:javascript
复制
import TestingViewControllers

将测试用例更改为:

代码语言:javascript
复制
func testExample() {


  var storyBoard: UIStoryboard?
  var anyVC: AnyObject?
  var viewController: TestingViewControllers.ViewController?

  storyBoard = UIStoryboard(name:"Main", bundle: nil)
  XCTAssert(storyBoard != nil, "Test Not Configured Properly")

  anyVC = storyBoard?.instantiateInitialViewController()
  viewController = anyVC as? TestingViewControllers.ViewController
  XCTAssert(viewController != nil, "Test Not Configured Properly")

  // This is an example of a functional test case.
  XCTAssert(true, "Pass")

}

测试用例通过

票数 0
EN

Stack Overflow用户

发布于 2016-12-22 20:23:53

你设置storyboardID了吗?如果你设置了,你可以像这样转换它。

您还需要将视图控制器类重命名为,例如,此处为MyAppViewController,生成主情节提要,使用它而不是标准的视图控制器类,然后将storyboardID设置为例如MyappVC

代码语言:javascript
复制
  var sut : MyAppViewController!

override func setUp() {
    super.setUp()

    // get a reference to storyboard and the correct
    // viewcontroller inside it. Remember to add
    // storyboardID in this case "MyappVC"


    let StoryBoard = UIStoryboard.init(name: "Main", bundle: nil)
    sut = StoryBoard.instantiateViewControllerWithIdentifier("Myapp VC")as!
    CalculatorViewController

    //trigger viewDidLoad()
    _ = sut.view
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25345010

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档