在Swift,Xcode6-Beta5中,我试图对我的"ViewController“进行单元测试,这不是一个很有创意的名字。
从其他响应来看,我认为我没有正确配置我的"Tests“目标。
失败的测试代码:
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")
}我可以用下面的几行代码来强制强制转换:
anyVC = storyBoard?.instantiateInitialViewController()
viewController = (anyVC != nil) ? (anyVC as ViewController) : nil但这导致了以下崩溃:
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类型的视图控制器,在故事板中没有其他东西。
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:
(lldb) po anyVC
(instance_type = Builtin.RawPointer = 0x00007fe22c92a290 -> 0x000000010e20bd80 (void *)0x000000010e20bea0: OBJC_METACLASS_$__TtC22TestingViewControllers14ViewController)
{
instance_type = 0x00007fe22c92a290 -> 0x000000010e20bd80 (void *)0x000000010e20bea0: OBJC_METACLASS_$__TtC22TestingViewControllers14ViewController
} 发布于 2014-08-20 02:52:31
我想出了一个比公开一切更好的解决方案。实际上,您只需要使用来自测试包的故事板,而不是使用nil (强制它来自主目标的包)。
var storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: NSBundle(forClass: self.dynamicType))
vc = storyboard.instantiateViewControllerWithIdentifier("LoginVC") as LoginViewController
vc.loadView()发布于 2014-08-19 05:06:07
感谢@Derrik Hathaway提供的解决方案的关键。应用程序和测试目标是不同的模块。
我的应用程序使用了一个不合适的名称TestingViewControllers来纠正这个问题,我做了以下更改,并在应用程序代码中将ViewController设为public类。
将这一行添加到测试用例中:
import TestingViewControllers将测试用例更改为:
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")
}测试用例通过
发布于 2016-12-22 20:23:53
你设置storyboardID了吗?如果你设置了,你可以像这样转换它。
您还需要将视图控制器类重命名为,例如,此处为MyAppViewController,生成主情节提要,使用它而不是标准的视图控制器类,然后将storyboardID设置为例如MyappVC
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.viewhttps://stackoverflow.com/questions/25345010
复制相似问题