Search code examples
androidsharedpreferencesmockito

How to mock a SharedPreferences using Mockito


I have just read about Unit Instrumented Testing in Android and I wonder how I can mock a SharedPreferences without any SharedPreferencesHelper class on it like here

My code is:

public class Auth {
private static SharedPreferences loggedUserData = null;
public static String getValidToken(Context context)
{
    initLoggedUserPreferences(context);
    String token = loggedUserData.getString(Constants.USER_TOKEN,null);
    return token;
}
public static String getLoggedUser(Context context)
{
    initLoggedUserPreferences(context);
    String user = loggedUserData.getString(Constants.LOGGED_USERNAME,null);
    return user;
}
public static void setUserCredentials(Context context, String username, String token)
{
    initLoggedUserPreferences(context);
    loggedUserData.edit().putString(Constants.LOGGED_USERNAME, username).commit();
    loggedUserData.edit().putString(Constants.USER_TOKEN,token).commit();
}

public static HashMap<String, String> setHeaders(String username, String password)
{
    HashMap<String, String> headers = new HashMap<String, String>();
    String auth = username + ":" + password;
    String encoding = Base64.encodeToString(auth.getBytes(), Base64.DEFAULT);
    headers.put("Authorization", "Basic " + encoding);
    return headers;
}

public static void deleteToken(Context context)
{
    initLoggedUserPreferences(context);
    loggedUserData.edit().remove(Constants.LOGGED_USERNAME).commit();
    loggedUserData.edit().remove(Constants.USER_TOKEN).commit();
}

public static HashMap<String, String> setHeadersWithToken(String token) {
    HashMap<String, String> headers = new HashMap<String, String>();
    headers.put("Authorization","Token "+token);
    return headers;
}
private static SharedPreferences initLoggedUserPreferences(Context context)
{
    if(loggedUserData == null)
        loggedUserData = context.getSharedPreferences(Constants.LOGGED_USER_PREFERENCES,0);
    return loggedUserData;
}}

Is is possible to mock SharedPreferences without creating other class on it?


Solution

  • So, because SharedPreferences comes from your context, it's easy:

    final SharedPreferences sharedPrefs = Mockito.mock(SharedPreferences.class);
    final Context context = Mockito.mock(Context.class);
    Mockito.when(context.getSharedPreferences(anyString(), anyInt())).thenReturn(sharedPrefs);
    
    // no use context
    

    for example, for getValidToken(Context context), the test could be:

    @Before
    public void before() throws Exception {
        this.sharedPrefs = Mockito.mock(SharedPreferences.class);
        this.context = Mockito.mock(Context.class);
        Mockito.when(context.getSharedPreferences(anyString(), anyInt())).thenReturn(sharedPrefs);
    }
    
    @Test
    public void testGetValidToken() throws Exception {
        Mockito.when(sharedPrefs.getString(anyString(), anyString())).thenReturn("foobar");
        assertEquals("foobar", Auth.getValidToken(context));
        // maybe add some verify();
    }