I am new in Android unit testing and I want to add some unit tests in an existing project. I am using the MVP design architecture. Inside my presenter, I have a call to PreferenceManager
in order to get the default SharedPrefences
but it always returns null. I have followed some tutorials and advices across stackoverflow on how to mock PreferenceManager
and SharedPreferences
but I can't make it work. This is my presenter class
@RunWith(MockitoJUnitRunner.class)
public class SettingsPresenterTest {
@Mock
private SettingsView mView;
@Mock
private LocalConfiguration conf;
private SettingsPresenter mPresenter;
public SettingsPresenterTest() {
super();
}
@Before
public void startUp() throws Exception {
MockitoAnnotations.initMocks(LocalConfiguration.class);
MockitoAnnotations.initMocks(PreferenceManager.class);
mPresenter = new SettingsPresenter(mView);
final SharedPreferences sharedPrefs =
Mockito.mock(SharedPreferences.class);
final Context context = Mockito.mock(Context.class);
Mockito.when(PreferenceManager.getDefaultSharedPreferences(context)).
thenReturn(sharedPrefs);
}
@Test
public void notificationsEnabledClicked() throws Exception {
boolean notifsEnabled = false;
mPresenter.notificationsEnabledClicked(notifsEnabled);
Mockito.verify(mView).setNotificationsView(notifsEnabled);
}
}
and here is the method where the SharedPreferences
are returned null
public class LocalConfiguration {
public TerritoryDto getLastSavedTerritory() {
SharedPreferences preferences =
PreferenceManager.getDefaultSharedPreferences(H.getContext());
String terrritoryString = preferences.getString(SAVED_TERRITORY,
null);
return
SerializerHelper.getInstance().deserialize(terrritoryString,
TerritoryDto.class);
}
}
Could you give me some guidelines on how to resolve this error?
Instead of directly referring to Android SDK, abstract that out from your presenter logics. What this means is, that instead of performing PreferenceManager.getDefaultSharedPreferences()
, create an abstraction and ask for territoryString
from your abstraction.
What will this give to you, is that your presenter won't know about the precense of neither PreferenceManager
nor SharedPreferences
, which are from Android SDK, thus you would have enough seams to perform pure unit testing.
Having said this, let's implement the abstractions. Having declared following interface:
public interface Storage {
@Nullable
String getSavedTerritory();
}
To which the concrete implementation would be:
public SharedPrefsStorage implements Storage {
private final SharedPreferences prefs;
public SharedPrefsStorage(Context context) {
prefs = PreferenceManager.getDefaultSharedPreferences();
}
@Nullable
@Override
public String getSavedTerritory() {
return prefs.getString(SAVED_TERRITORY, null);
}
}
Then your presenter would become something like this:
public class LocalConfiguration {
final Storage storage;
public LocalConfiguration(Storage storage) {
this.storage = storage;
}
public TerritoryDto getLastSavedTerritory() {
final String territory = storage.getSavedTerritory();
return SerializerHelper.getInstance().deserialize(territory, TerritoryDto.class);
}
}
This would give you a seam to perform pure unit testing:
@Test
void someTest() {
when(storage.getSavedTerritory()).thenReturn("New York");
...
}
No need to worry about mocking PreferenceManager
anymore.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With