OCUnit测试从命令行失败,但在使用Keychain Services时在Xcode中工作

时间:2012-04-03 15:32:19

标签: ios unit-testing continuous-integration ocunit sfhfkeychainutils

我正在使用SFHFKeychainUtils在我的应用中使用Keychain服务。我写了一些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

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

3 个答案:

答案 0 :(得分:8)

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

exec osascript <<EOF

tell application "iOS Simulator"

activate

end tell

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

答案 1 :(得分: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

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

答案 2 :(得分:0)

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

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

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