在 Swift 单元测试中,我在应用和单元测试目标之间收到类转换错误



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

在我的 ViewController 初始化时,我向提供程序查询数据并接收同步响应。然后,提供程序尝试使用对 Web 的异步调用刷新数据,如果已更改,则发送将由 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);

下面是在视图控制器中处理通知的函数。它工作正常:

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);
}
}
}

在提供程序中,一旦我收到来自 Web 的异步响应,我就会发送带有 userInformation 中的新数据的通知:

var dict = Dictionary<String, myCustomStruct>();
dict.updateValue(newData, forKey: newData.objectId);
let msg = Notification(name: NotificationName, object: nil, userInfo: dict)
NotificationCenter.default.post(msg);

上面的所有代码都工作正常,但是在我的单元测试中,当我的视图控制器捕获通知时,我收到一个错误,说单元测试目标的 myCustomStruct 无法强制转换为应用程序目标中的 myCustomStruct:

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

我已经检查过了,自定义结构可用于两个目标。

这是我的测试:

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);
}

好的,经过长时间的研究没有任何回应,我"找到"了我的问题的解决方案。使用这个堆栈溢出帖子的信息,我尝试了一些猴子业务的事情,但错误消失了。

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

现在它正在工作,我可以继续使用我的 Swift TDD。但是,如果有人可以解释为什么这是测试的正确配置,我建议为我的下一个孩子提供您的名字。

谢谢和问候。

最新更新