Nicola Giancecchi
Nicola Giancecchi

Reputation: 3065

Trying to mock SharedPreferences using Mockito

I'm trying to use Mockito to test a settings manager which saves data through SharedPreferences.

Since SharedPreferences makes use of Context, I need to use mock classes.

This is my settings manager class:

public class SettingsManager implements ISettingsManager {

    protected SharedPreferences prefs;

    public SettingsManager(SharedPreferences prefs) {
        this.prefs = prefs;
    }

    private boolean getBooleanPreference(String key) {
        return prefs.getBoolean(key, true);
    }

    private void setBooleanPreference(boolean enabled, String key) {
        SharedPreferences.Editor editor = prefs.edit();
        editor.putBoolean(key, enabled);
        editor.commit();
    }
}

This is the test case I wrote:

Context mContext = Mockito.mock(Context.class);
SharedPreferences mSharedPreference = Mockito.mock(SharedPreferences.class);
SharedPreferences.Editor mEditor = Mockito.mock(SharedPreferences.Editor.class, Mockito.RETURNS_DEEP_STUBS);
Mockito.when(mSharedPreference.edit()).thenReturn(mEditor);
Mockito.when(mEditor.commit()).thenReturn(true);
Mockito.when(mEditor.putBoolean(Mockito.anyString(), Mockito.anyBoolean())).thenReturn(mEditor);

SettingsManager manager = new SettingsManager(mSharedPreference);
boolean current = manager.areNotificationsEnabled();
manager.setNotificationsEnabled(!current);
boolean newValue = manager.areNotificationsEnabled();
Assert.assertTrue(newValue != current);

The problem is when I set the setNotificationsEnabled flag, the newValue remains the same of current: SharedPreferences does not persist data. How can I save data to SharedPreferences while testing?

Upvotes: 1

Views: 1347

Answers (2)

David Rawson
David Rawson

Reputation: 21487

Robolectric is an option for this kind of integration test.

Robolectric provides test doubles called "shadows" of common Android classes like Context, SQLiteDatabase and SharedPreferences. The tests you write run in test in your IDE (not androidTest on an emulator or test device) so it is easier to configure tools for test coverage.

The shadow SharedPreference is sandboxed as well so it won't interfere with the actual SharedPreferences on a device.

Upvotes: 3

Antimatéria
Antimatéria

Reputation: 159

Convert this to an AndroidTest and use InstrumentationRegistry.getTargetContext() to get a context, this way you can use the class without mocking it

Upvotes: 2

Related Questions