I have a problem with instrumental test that is checking activity that in one of methods saves its state to shared preferences. Tested code looks like that:
initialPresenter.getLocalData().edit()
.putString("SessionDetails", new Gson().toJson(sessionData))
.putBoolean("relog", false)
.apply();
LocalData is injected into presenter by dagger2. I've created mocks for it and I'm repleacing them so everything works fine there; eg.
when(localData.getBoolean("signed_using_email", false)).thenReturn(true);
Problem occurs when I'm trying to somehow disable or ommit editing data. I've created another mock; this time of editor so when SharedPref calls edit it gets explicit mock;
@Mock SharedPreferences.Editor mEditor;
.
.
.
when(localData.edit()).thenReturn(mEditor);
but then I get error:
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
Which btw. is freaking weird, why on putBoolean no putString? It seems like first mock works just fine, but then it gets nested (?) and throws error.
Also tried another approach, instead of stubbing/replacing answer I've used doNothing;
doNothing().when(localData).edit();
But it also caused similar problem throwing error:
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
Any ideas how to fix it? I don't need to save any state, I can mock it later, which is fine because I'll get documentation then by writing these tests. Earlier I was using PowerMockito to suppress whole method that uses sharedPreferences but this solution doesn't seem to be to good.