在Swift单元测试中,我在App和单元测试目标之间得到了一个类强制转换错误

时间:2017-07-01 16:44:40

标签: ios unit-testing swift3 xcode8

在iOS 10中,Swift 3应用程序我尝试使用NotificationCenter测试ViewController。

在我的ViewController初始化中,我向提供者查询数据并接收同步响应。然后,提供程序尝试使用对Web的异步调用来刷新数据,如果已更改,则发送将由ViewController捕获的通知。这是我的ViewController初始化的一部分:

class func instantiateWithId(_ id: String, provider: DataProvider) -> MyViewController {

   let storyboard = UIStoryboard(name: "Main", bundle: Bundle(for:MyViewController.self));
   let controller = storyboard.instantiateViewController(withIdentifier: "ViewControllerId") as! MyViewController;

   controller.dataProvider = provider;
   controller.objectId = id;
   controller.object = controller.dataProvider!.getObject(id: id, completion: controller.refreshObject);

   return controller; 
}

初始化后,我注册了正常工作的通知观察者:

NotificationCenter.default.addObserver(self, selector: #selector(self.catchNotification), name: NotificationName, object: nil);

这是在ViewController中处理通知的函数。工作正常:

func catchNotification(notification: NSNotification) -> Void {

   guard (notification.name == NotificationName) else {return;}
   let info = notification.userInfo as! [String: Any];
   if info.count > 0 {

       guard (info[objectId] != nil) else {return;}
       if let value = info[objectId] as! MyCustomStruct? {
           self.refreshData(updated: value);
       }
    }
}

在Provider中,一旦我收到来自web的异步响应,我就会在userInfo中发送包含新数据的通知:

var dict = Dictionary<String, myCustomStruct>();
dict.updateValue(newData, forKey: newData.objectId);

let msg = Notification(name: NotificationName, object: nil, userInfo: dict)
NotificationCenter.default.post(msg);

上面的所有代码都运行正常,但在我的单元测试中,当我的ViewController捕获通知时,我发出错误,说单元测试目标的myCustomStruct无法转换为应用程序目标中的myCustomStruct:

Could not cast value of type ‘ApplicationUnitTests.MyCustomStruct’ (0x1161fa828) to ‘Application. myCustomStruct' (0x1057fd6d0).

我已经检查过,两个目标可以使用CustomStruct。

这是我的测试:

func testViewControllerInitialization() {
   let fixture = MockDataProvider();
   let sutId = fixture.testId;
   let sut = MyViewController.instantiateWithId(sutId, provider: fixture)

   _ = sut.view;
   XCTAssertNotNil(sut, "SUT not initialized");
   XCTAssertNotNil(sut.object, "Object Not Loaded!");
   XCTAssertEqual(sutId, sut.object!.objectId, "Differente ObjectId expected!");

   let newValue = "changed";
   var nextFixture = fixture.getObject(objectId: sutId, completion: {(result) in return;});
   nextFixture.name = newValue;

   fixture.refreshObject(newData: nextFixture); <- This function send the notification
   sleep(1);
   XCTAssertEqual(newValue, sut.object!.name);
}

1 个答案:

答案 0 :(得分:0)

好的,经过长时间的研究,没有任何回应,我'找到'解决我的问题。使用this stackoverflow帖子的信息,我尝试了一些猴子业务,错误消失了。

实际上,解决问题的方法是禁用UnitTest Target的主要故事板。我启用了它,因为问题中列出了instantiateWithId方法。根据我的理解,有必要将它链接到测试目标,以在测试目标使用的代码中实例化它。但由于某种原因,这是一个错误的事情。

现在它正在运行,我可以继续使用我的Swift TDD。但是,如果有人可以告诉我为什么这是测试的正确配置我会为你的下一个孩子提供你的名字。

谢谢和问候。