7

我正在使用 SFHFKeychainUtils 在我的应用程序中使用钥匙串服务。我编写了一些 OCUnit 测试来验证此代码的功能。当我在 iOS 模拟器或我的设备上从 Xcode 运行单元测试时,一切正常。但是现在我正在尝试设置一个 CI 服务器,并且当它通过命令行运行时测试失败,错误代码为 -25291。查看 Apple 的文档告诉我:没有可用的信任结果 (errSecNotAvailable)。我已将 Security.framework 链接到我的单元测试项目,从我在网上阅读的内容看来,这就是我需要让它工作的全部内容。这是我在控制台中调用的命令:

/usr/bin/xcodebuild -target [Test_Target] -sdk /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.1.sdk/ -configuration Debug

有没有人有任何经验或建议让单元测试和钥匙串服务从命令行很好地协同工作?

4

3 回答 3

8

我遇到了同样的问题,我的解决方案是在开始任何测试之前确保模拟器正在运行。我在 Xcode 的 Run Script 构建阶段使用 AppleScript 做到了这一点,在 CI 服务器上基本相同。这是将打开模拟器的 shell 脚本:

exec osascript <<EOF

tell application "iOS Simulator"

activate

end tell

导致此问题的安全/钥匙串服务问题显然是一个已知问题,尽管我还没有跟踪它的雷达。如果您使用 Jenkins,请将上述脚本置于 Xcode 构建阶段之前的 Execute Shell 阶段。如果您通过 Xcode 本身控制它,请将其置于 RunUnitTests 运行脚本构建阶段之前的运行脚本构建阶段。希望能解决您的问题!

于 2012-05-31T19:27:32.397 回答
1

当从命令行运行 OCUnit 测试时,我无法弄清楚为什么钥匙串访问失败。

为了继续我的测试,我在我的单元测试目标中添加了一个 hacktastic 类别:

//
//  SFHFKeychainUtils+UnitTestHacks.m
//  CB30
// 
// GRRR!!! http://stackoverflow.com/questions/9996578/ocunit-tests-fail-from-the-command-line-but-work-in-xcode-when-using-keychain-se
//
//  Created by Joshua Vickery on 5/14/12.
//

#import "SFHFKeychainUtils+UnitTestHacks.h"

static NSMutableDictionary *fakeKeyChainHolder;

@implementation SFHFKeychainUtils (UnitTestHacks)

+ (NSMutableDictionary *)fakeKeyChainForServiceName:(NSString *)serviceName {
    if (nil == fakeKeyChainHolder) {
        fakeKeyChainHolder = [NSMutableDictionary dictionary];
    }

    NSMutableDictionary *fakeKeyChain = [fakeKeyChainHolder objectForKey:serviceName];
    if (nil == fakeKeyChain) {
        fakeKeyChain = [NSMutableDictionary dictionary];
        [fakeKeyChainHolder setObject:fakeKeyChain forKey:serviceName];
    }
    return fakeKeyChain;
}

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"

+ (BOOL) deleteItemForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error 
{
    [[self fakeKeyChainForServiceName:serviceName] removeObjectForKey:username];
    return YES;
}


+ (BOOL) storeUsername: (NSString *) username andPassword: (NSString *) password forServiceName: (NSString *) serviceName updateExisting: (BOOL) updateExisting error: (NSError **) error 
{
    [[self fakeKeyChainForServiceName:serviceName] setObject:password forKey:username];
    return YES;
}

+ (NSString *) getPasswordForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error 
{
    return [[self fakeKeyChainForServiceName:serviceName] objectForKey:username];
}

#pragma clang diagnostic pop

@end

请注意,这不是一个好的解决方案,而是让单元测试工作直到找到更好的解决方案的变通方法。

于 2012-05-14T19:28:50.090 回答
0

我遇到了类似的问题。根据我的研究,这可能归结为测试运行时正在运行的模拟器版本。如果从命令行运行,使用 iphone 模拟器 6.0 对钥匙串进行单元测试总是会让我的测试失败。将其更改为任何其他版本(4.3、5.0、5.1)并且它们通过了。任何版本的 XCode 总是很好。

也许这是一个命令行工具问题,在运行测试之前没有设置一些必要的标志。

我在这里用一个小测试用例提出了一个新问题:Keychain Services API failed with errSecNotAvailable in iphonesimulator 6.0

于 2012-10-29T10:42:47.083 回答