2014-10-09 72 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

您必須的appDelegate這是實際用戶的默認值,而不是你的模擬使用[NSUserDefaults standardUserDefaults]

一個解決方案是讓用戶默認的應用程序委託的財產,並與您mockUserDefaults在測試中進行設置。

另一個是在您的測試中調試[NSUserDefaults standardUserDefaults]以返回您的mockUserDefaults

+0

我試着在appDelegate上設置一個屬性,並且這樣做,但仍然得到了相同的結果。我更新了我的帖子以顯示我所做的更改。我錯過了什麼? – Hodson 2014-10-09 14:12:47

+0

您在應用程序委託中使用了哪些用戶默認設置? – 2014-10-09 14:15:26

+0

在'application:didFinishLaunchingWithOptions:'我設置'self.userDefaults'爲'standardUserDefaults',然後馬上檢查'currentUser'鍵。這個值的結果決定了將'rootViewController'設置爲什麼。 – Hodson 2014-10-09 14:18:10

1

所以非常感謝Ken Kuan,我設法解決了我遇到的問題。下面我是如何實現它的。

我添加了一個NSUserDefaults屬性的AppDelegate和setter函數。

我將self.userDefaults設置爲[NSUserDefaults standardUserDefaults],application:willFinishLaunchingWithOptions:

我再application:didFinishLaunchingWithOptions:

設置rootViewController 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 2014-10-09 15:46:21

+2

我認爲你應該把初始用戶默認放在' - (BOOL)應用程序中:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions'並設置根視圖控制器在完成加載。在didBecomeActive中設置根視圖控制器是不必要的,因此每次從後臺調用或退出活動狀態(例如打開控制面板) – 2014-10-09 16:46:02

+0

這是一個很好的觀點。我已經更新了我的答案。 – Hodson 2014-10-10 08:50:35

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];