2014-10-09 9 views
0

Мне кажется, что я не могу издеваться над NSUserDefaults. Я хочу, чтобы он отправлял обратно данные, которые я ему рассказывал, но вместо этого он отправляет обратно данные, хранящиеся в нем, при запуске приложения.Не удалось издеваться над NSUserDefaults

Я использую:

  • Specta
  • Expecta
  • OCMockito

У меня есть следующий тест:

describe(@"AppDelegate", ^{ 
    __block AppDelegate *appDelegate; 

    beforeEach(^{ 
     appDelegate = [AppDelegate new]; 
    }); 

    afterEach(^{ 
     appDelegate = nil; 
    }); 

    describe(@"application did finish launching with options", ^{ 
     beforeEach(^{ 
      [appDelegate application:nil didFinishLaunchingWithOptions:nil]; 

      NSUserDefaults *mockUserDefaults = mock([NSUserDefaults class]); 
      [given([mockUserDefaults objectForKey:@"currentUser"]) willReturn:nil]; 

     }); 

     it(@"should have a login view controller as root view controller", ^{ 
      expect(appDelegate.window.rootViewController).to.beKindOf([ToALoginViewController class]); 
     }); 
    }); 
}); 

Так выше тест терпит неудачу, потому что он фактически возвращает некоторые данные для currentUser. Что я делаю не так?


Исходя из того, что сказал Кен Кван, я сделал следующие изменения:

AppDelegate.h

@property (strong, nonatomic) NSUserDefaults *userDefaults; 

- (void)setUserDefaults:(NSUserDefaults *)userDefaults; 

AppDelegate.m

- (void)setUserDefaults:(NSUserDefaults *)userDefaults { 
    _userDefaults = userDefaults; 
} 

AppDelegateSpec.m

beforeEach(^{ 
    [appDelegate application:nil didFinishLaunchingWithOptions:nil]; 

    NSUserDefaults *mockUserDefaults = mock([NSUserDefaults class]); 
    [appDelegate setUserDefaults:mockUserDefaults]; 
    [given([mockUserDefaults objectForKey:@"currentUser"]) willReturn:nil]; 

}); 

Однако, я все еще получаю ту же проблему.

ответ

1

Вы должны использовать [NSUserDefaults standardUserDefaults] в appDelegate, который является фактическим значением по умолчанию пользователя, а не вашим макетом.

Решение состоит в том, чтобы предоставить пользователю по умолчанию свойство делегата приложения и установить его с помощью mockUserDefaults в тестах.

Еще один вариант - поднять [NSUserDefaults standardUserDefaults], чтобы вернуть mockUserDefaults в свои тесты.

+0

Я попытался установить свойство на appDelegate и сделать это таким образом, но все же получил тот же результат. Я обновил свой пост, чтобы показать изменения, которые я сделал. Я что-то пропустил? – Hodson

+0

Где вы использовали пользовательские значения по умолчанию в делегате приложения? –

+0

В 'application: didFinishLaunchingWithOptions:' Я устанавливаю 'self.userDefaults' в' standardUserDefaults', а затем сразу же проверяю ключ 'currentUser'. Результат этого значения затем определяет, как установить 'rootViewController' как. – Hodson

1

Так что благодаря Кэну Куану мне удалось решить проблему, с которой я столкнулся. Вот как я это достигла.

Я добавил NSUserDefaults собственности AppDelegate и функции сеттера.

Я установил self.userDefaults в [NSUserDefaults standardUserDefaults] в application:willFinishLaunchingWithOptions:.

Я тогда установить rootViewController в application:didFinishLaunchingWithOptions:

AppDelegate.h

@property (strong, nonatomic) NSUserDefaults *userDefaults; 

- (void)setUserDefaults:(NSUserDefaults *)userDefaults; 

AppDelegate.м

- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    self.userDefaults = [NSUserDefaults standardUserDefaults]; 

    return YES; 
} 

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 

    NSData *encodedUserData = [self.userDefaults objectForKey:@"currentUser"]; 
    if (encodedUserData) { 
     NSLog(@"Have current user"); 
     self.window.rootViewController = [ThermostatViewController new]; 
    } else { 
     NSLog(@"No current user"); 
     self.window.rootViewController = [ToALoginViewController new]; 
    } 

    [self.window makeKeyAndVisible]; 

    return YES; 
} 

- (void)setUserDefaults:(NSUserDefaults *)userDefaults { 
    _userDefaults = userDefaults; 
} 

AppDelegateSpec.m

describe(@"application will finish launching with options", ^{ 
    beforeEach(^{ 
     [appDelegate application:nil willFinishLaunchingWithOptions:nil]; 
    }); 

    context(@"application did finish launching with options and with no current user", ^{ 
     beforeEach(^{ 
      NSUserDefaults *mockUserDefaults = mock([NSUserDefaults class]); 
      [appDelegate setUserDefaults:mockUserDefaults]; 
      [given([mockUserDefaults objectForKey:@"currentUser"]) willReturn:nil]; 

      [appDelegate application:nil didFinishLaunchingWithOptions:nil]; 
     }); 

     it(@"should have a login view controller as root view controller", ^{ 
      expect(appDelegate.window.rootViewController).to.beKindOf([ToALoginViewController class]); 
     }); 
    }); 
}); 
+0

Я не могу принять это в течение 2 дней в качестве своего собственного ответа. В то же время, не стесняйтесь улучшать его. – Hodson

+2

Я думаю, что вы должны поместить первоначальный пользовательский по умолчанию в приложение '- (BOOL): (UIApplication *) приложение будет FinishLaunchingWithOptions: (NSDictionary *) launchOptions' и установить контроллер корневого представления в завершение загрузки. Настройка контроллера корневого представления в didBecomeActive не требуется, поэтому он будет вызываться каждый раз из фона или отменять активный (например, открыть панель управления) –

+0

Это очень хороший момент. Я обновил свой ответ. – Hodson

2

Вы можете издеваться NSUserDefaults. У меня есть этот код, который работает нормально. Когда вы издеваетесь над NSUserdefaults, убедитесь, что вы заканчиваете макет в конце тестового примера, иначе это приведет к ошибкам в других местах, где вы используете NSUserDefaults.

id userDefaultsMock = OCMClassMock([NSUserDefaults class]); 

OCMStub([userDefaultsMock standardUserDefaults]).andReturn(userDefaultsMock); 

OCMStub([[userDefaultsMock standardUserDefaults] boolForKey:SHOWMYNAME]).andReturn(@"N"); 

[self.myObject codewithuserdefaults]; 

OCMVerify([[NSUserDefaults standardUserDefaults] setValue:[OCMArg any] forKey:FIRSTNAME]); 

[userDefaultsMock stopMocking]; 
Смежные вопросы