コマンド ラインから OCUnit テストを実行すると、キーチェーン アクセスが失敗する理由がわかりませんでした。
テストを進めるために、ユニット テストのターゲットにハックタスティック カテゴリを追加しました。
//
// 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
これは良い解決策ではありませんが、より良い解決策が見つかるまで単体テストを機能させるための回避策であることに注意してください。