我正在尝试使用ReactiveCocoa和Kiwi进行测试,使用CocoaPods进行依赖性管理来建立一个新项目。
我为一个典型的登录屏幕设置了第一个测试,在用户输入用户名和密码之前,登录按钮不会启用。只是一些示例代码的简单版本:
- (void)viewDidLoad
{
[super viewDidLoad];
RAC(self.loginButton, enabled) = [RACSignal combineLatest:@[self.userNameField.rac_textSignal,
self.passwordField.rac_textSignal]
reduce:^(NSString *username, NSString *password) {
return @(username.length > 0 && password.length > 0);
}];
}
问题是,当我运行测试时,我会得到以下错误:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Value from stream <RACDynamicSignal: 0xe3735a0> name: +combineLatest: (
"<RACDynamicSignal: 0xe368c50> name: <UITextField: 0xe3707a0> -rac_textSignal",
"<RACDynamicSignal: 0xe372d80> name: <UITextField: 0xe36aef0> -rac_textSignal"
) is not a tuple: <RACTuple: 0xe377a40> (
"",
""
)'
当然,它是一个RACTuple
,所以这只是令人困惑。
我的研究发现了以下关于ReactiveCocoa的问题:
https://github.com/ReactiveCocoa/ReactiveCocoa/issues/901
那里的诊断是,ReactiveCocoa不知何故被联系了两次。在那里遇到问题的人抛弃了CocoaPods,解决了这个问题。这似乎不对。有人让它工作了吗?
为了完整起见,我的播客文件是:
platform :ios, '6.0'
pod 'ReactiveCocoa'
target :test do
link_with 'PollVaultTests'
pod 'Kiwi/XCTest'
end
好吧,我要回答我自己的问题了。
事实证明,当pod在Podfile
中以"全局"级别列出时,CocoaPods会将它们包含在所有目标中。
本例的结果是,我的主要项目链接在CocoaPods中,我的测试目标也是如此。
当我的测试目标被注入到我的主项目中以运行测试时,你会得到两次ReactiveCocoa链接。因此,有两个名为RACTuple
的类四处浮动,因此,当ReactiveCocoa代码内部检查以确保其参数是RACTuple
时,它会检查该类的错误副本,并有效地得到假阴性结果。
解决方案是确保我在Podfile
中的测试目标配置为仅在中链接测试吊舱,如下所示:
platform :ios, '6.0'
pod 'ReactiveCocoa'
target :test, :exclusive => true do
link_with 'PollVaultTests'
pod 'Kiwi/XCTest'
end
:exclusive => true
部分是告诉Cocoapods在我的测试目标中只包含Kiwi测试框架的部分。问题解决了!