Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Android Mock Shared Preference for unit testing. (NOTE: The intention here is to avoid mocking lots of API related to `SharedPreferences`, as outcome from interacting with `SharedPreferences` is not relevant in the unit test.). Please comment if there is a cleaner way of doing this.
import android.content.SharedPreferences;
import android.support.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* Mock implementation of shared preference, which just saves data in memory using map.
*/
public class MockSharedPreference implements SharedPreferences {
private final HashMap<String, Object> preferenceMap;
private final MockSharedPreferenceEditor preferenceEditor;
public MockSharedPreference() {
preferenceMap = new HashMap<>();
preferenceEditor = new MockSharedPreferenceEditor(preferenceMap);
}
@Override
public Map<String, ?> getAll() {
return preferenceMap;
}
@Nullable
@Override
public String getString(final String s, @Nullable final String s1) {
return (String) preferenceMap.get(s);
}
@Nullable
@Override
public Set<String> getStringSet(final String s, @Nullable final Set<String> set) {
return (Set<String>) preferenceMap.get(s);
}
@Override
public int getInt(final String s, final int i) {
return (int) preferenceMap.get(s);
}
@Override
public long getLong(final String s, final long l) {
return (long) preferenceMap.get(s);
}
@Override
public float getFloat(final String s, final float v) {
return (float) preferenceMap.get(s);
}
@Override
public boolean getBoolean(final String s, final boolean b) {
return (boolean) preferenceMap.get(s);
}
@Override
public boolean contains(final String s) {
return preferenceMap.containsKey(s);
}
@Override
public Editor edit() {
return preferenceEditor;
}
@Override
public void registerOnSharedPreferenceChangeListener(final OnSharedPreferenceChangeListener onSharedPreferenceChangeListener) {
}
@Override
public void unregisterOnSharedPreferenceChangeListener(final OnSharedPreferenceChangeListener onSharedPreferenceChangeListener) {
}
public static class MockSharedPreferenceEditor implements Editor {
private final HashMap<String, Object> preferenceMap;
public MockSharedPreferenceEditor(final HashMap<String, Object> preferenceMap) {
this.preferenceMap = preferenceMap;
}
@Override
public Editor putString(final String s, @Nullable final String s1) {
preferenceMap.put(s, s1);
return this;
}
@Override
public Editor putStringSet(final String s, @Nullable final Set<String> set) {
preferenceMap.put(s, set);
return this;
}
@Override
public Editor putInt(final String s, final int i) {
preferenceMap.put(s, i);
return this;
}
@Override
public Editor putLong(final String s, final long l) {
preferenceMap.put(s, l);
return this;
}
@Override
public Editor putFloat(final String s, final float v) {
preferenceMap.put(s, v);
return this;
}
@Override
public Editor putBoolean(final String s, final boolean b) {
preferenceMap.put(s, b);
return this;
}
@Override
public Editor remove(final String s) {
preferenceMap.remove(s);
return this;
}
@Override
public Editor clear() {
preferenceMap.clear();
return this;
}
@Override
public boolean commit() {
return true;
}
@Override
public void apply() {
// Nothing to do, everything is saved in memory.
}
}
}
@patrickfav

This comment has been minimized.

Copy link

patrickfav commented Jul 9, 2018

Unfortunately this does not mock the transaction style behavior with using the editor. If you e.g. put or remove an item, the update will be reflected no matter if commit or apply is called.

@amardeshbd

This comment has been minimized.

Copy link
Owner Author

amardeshbd commented Apr 8, 2019

Yes, it's correct. It's meant to be drop-in replacement instead of mocking almost everything related to SharedPreferences, where the functionality and outcome related to SharedPreferences does not matter.

Otherwise, you have to mock a lot of API available in the Editor. Here is a kotlin example on how I sometime mock specific things.

    private val preferences: SharedPreferences = mock(SharedPreferences::class.java)
    private val editor = mock(SharedPreferences.Editor::class.java)


    @Before
    fun setup() {
        `when`(editor.putBoolean(anyString(), anyBoolean())).thenReturn(editor) // Also mock `putString`, `putFloat` and so on
        `when`(preferences.edit()).thenReturn(editor)
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.