7

我正在使用SFHFKeychainUtils在我的应用中使用Keychain服务。我已经写了一些OCUnit测试来验证这段代码的功能。当我在iOS模拟器或我的设备上从Xcode运行单元测试时,一切正常。但是现在我试图建立一个CI服务器,当它通过错误代码-25291的命令行运行时,测试失败。看看苹果的文档告诉我:没有信任结果可用(errSecNotAvailable)。我已经将Security.framework链接到了我的单元测试项目,看起来就像从我在网上阅读的内容中看到的那样,这是我所需要的全部工作。下面是一个命令我调用控制台:OCUnit测试在命令行失败,但在使用Keychain服务时在Xcode中工作

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

没有人有越来越单元测试和钥匙扣服务很好地一起在命令行中播放任何经验或建议吗?

+0

是否运行在无头模式的CI服务器,或者你有一个活跃的用户会话? – 2012-04-04 08:26:36

+0

我有一个活动的用户会话。 – 2012-04-06 17:11:43

+0

很奇怪,你能否确认你有权访问钥匙串,即它没有密码保护? – 2012-04-26 08:45:29

回答

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构建阶段。 希望能解决您的问题!

+0

谢谢。在搜索该问题之前,我花了一个小时的时间。剧本完全按照您的建议工作。 – makdad 2012-06-04 09:47:37

+0

清理 - 您可能需要检出WaxSim项目。这使您可以从命令行启动模拟器。 https://github.com/square/WaxSim/ - 你也可以使用下面的命令杀死任何活跃的模拟游戏的ps aux | grep -e'iPhone Simulator.app'| grep -v grep | awk'{print $ 2}'| xargs kill -9' – 2012-07-18 07:30:08

+1

@stuart ...而不是复杂的grep和aux解决方案...你应该可以使用“killall -9”iPhone模拟器'“ – 2012-10-24 20:13:17

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 

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

+1

我仍然认为这是一种很好的解决方案,因为你有效地嘲笑框架,在单元测试中从来不是一件坏事.. – makdad 2012-09-14 05:46:20

0

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

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

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

相关问题