2016-12-07 38 views
1

我有一個工具測試問題,它檢查在其中一種方法中將其狀態保存爲共享首選項的活動。經測試的代碼如下所示:使用Mockito和Dagger的SharedPreferences

initialPresenter.getLocalData().edit() 
        .putString("SessionDetails", new Gson().toJson(sessionData)) 
        .putBoolean("relog", false) 
        .apply(); 

LocalData通過dagger2注入演示者。我已經爲它創建了模擬,並且我正在補充它們,所以在那裏一切正常。例如。

when(localData.getBoolean("signed_using_email", false)).thenReturn(true); 

當我試圖以某種方式禁用或忽略編輯數據時會出現問題。我創造了另一個模擬;這次的編輯器,所以當SharedPref調用編輯它顯式模擬;

@Mock SharedPreferences.Editor mEditor; 
. 
. 
. 
when(localData.edit()).thenReturn(mEditor); 

但後來我得到錯誤:

Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'android.content.SharedPreferences$Editor android.content.SharedPreferences$Editor.putBoolean(java.lang.String, boolean)' on a null object reference 

其中順便說一句。怪嚇人怪異,爲什麼putBoolean沒有putString?它看起來像第一個模擬工程很好,但它然後嵌套(?)並拋出錯誤。

也嘗試了另一種方法,而不是樁/替換答案我用過沒有;

doNothing().when(localData).edit(); 

但它也造成了類似的問題拋出錯誤:

org.mockito.exceptions.base.MockitoException: 
Only void methods can doNothing()! 
Example of correct use of doNothing(): 
doNothing(). 
doThrow(new RuntimeException()) 
.when(mock).someVoidMethod(); 
Above means: 
someVoidMethod() does nothing the 1st time but throws an exception the 2nd time is called 

任何想法如何解決呢?我不需要保存任何狀態,以後我可以嘲笑它,這很好,因爲我會通過編寫這些測試來獲得文檔。早些時候,我使用PowerMockito來壓縮使用sharedPreferences的整個方法,但是這個解決方案似乎並不好。

+1

你的問題本質上是如何模擬'SharedPreferences.Editor'的'builder'語法。查看[Jeff Bowman的回答](https://stackoverflow.com/questions/8501920/how-to-mock-a-builder-with-mockito)瞭解如何使用Mockito完成此操作。換句話說,嘗試'@Mock(answer = RETURNS_SELF)SharedPreferences.Editor mEditor;' –

+0

@DavidRawson謝謝!我已經改變了創建模擬爲 mEditor = mock(SharedPreferences.Editor.class,RETURNS_DEEP_STUBS); 它似乎工作。你能發表你的評論作爲答案,所以我可以接受它嗎? :) – Kamajabu

回答

2

這裏的問題是,SharedPreferences.Editor有一個「構建器」語法,其中每個調用putString(),putBoolean()等返回Editor

當你模擬這個對象時,你想通過每次調用這些方法之一時模擬自身返回來模仿這種行爲。

Jeff Bowman's answer上嘲諷建設者語法用的Mockito,你可以在你的代碼如下變化做到這一點:

@Mock(answer = RETURNS_SELF) SharedPreferences.Editor mEditor; 

或者,你可能只是想利用RETURNS_DEEP_STUBS

mEditor = mock(SharedPreferences.Editor.class, RETURNS_DEEP_STUBS);