Skip to content

Instantly share code, notes, and snippets.

@hossain-khan
Last active March 13, 2020 18:13
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save hossain-khan/354173d00b988574ee5019c4ba0c8a0b to your computer and use it in GitHub Desktop.
Save hossain-khan/354173d00b988574ee5019c4ba0c8a0b to your computer and use it in GitHub Desktop.
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
Copy link

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.

@hossain-khan
Copy link
Author

hossain-khan 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