Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mock PreferenceManager in Android?

I've written a class that is using Context, a third party library and SharedPreferences from PreferenceManager.

It's possible to mock Context, the third party library can be mocked using some mocking framework, but what to do with PreferenceManager?

I have two methods:

public void saveString(ThirdPartyObject obj) {
    SharedPreferences appPreferences = 
        PreferenceManager.getDefaultSharedPreferences(mContext);
    SharedPreferences.Editor editor = appPreferences.edit();
    editor.putString(mContext.getString(
        R.string.preferences_string_name), obj.getString());
    editor.commit();
}

and corresponding, that loads preferences.

like image 741
pixel Avatar asked Jul 26 '10 17:07

pixel


2 Answers

It doesn't look like you actually want a mock instance of PreferenceManager (which is mostly used in a PreferenceFragment or PreferenceActivity).

You probably want either:

  1. A mock SharedPreferences, in which case you can just mock Context#getSharedPreferences (which is called by PreferenceManager#getDefaultSharedPreferences anyhow). You'll probably also have to make a mock SharedPreferences.Editor if preferences are edited, as above. You say you already know how to mock the context, so this should be fairly straightforward.

  2. To use the actual preferences in the environment. This is easiest, and not necessarily a bad idea. Do make certain it's cleaned up properly so that your tests don't interfere with each other (or, depending on your test environment, aren't affected by manual use of the app).

If you really do want to mock PreferenceManager instance (like that you get in PreferenceFragment or PreferenceActivity), you can absolutely do so.

Since it's non-final, you can generate a mock PreferenceManager and SharedPreferences using Mockito (or another mocking library) as long as you have a way to provide it to your code wherever you would ordinarily get one (in non-test code, this normally comes from the getPreferenceManager()).

like image 77
Jeremy Roman Avatar answered Nov 02 '22 04:11

Jeremy Roman


You can use specialized context for shared preference. RenamingDelegatingContext delegates everything to a Context. When we access SharedPreference from a Context, we use getSharedPreferences(String name, int mode).

Here by extending RenamingDelegatingContext we override getSharedPreferences and pretend the name parameter with test PREFIX, So when test runs it will write to preference file which is different then main application.

public class SpecializedMockContext extends RenamingDelegatingContext {
    public static final String PREFIX = "test.";

    public SpecializedMockContext(Context context) {
        super(context, PREFIX);
    }

    @Override
    public SharedPreferences getSharedPreferences(String name, int mode) {
        return super.getSharedPreferences(PREFIX + name, mode);
    }
}

Set this SpecialisedMockContext to your test Application context. setContext(specialisedMockContext) and createApplication().

like image 3
Vijay Vankhede Avatar answered Nov 02 '22 03:11

Vijay Vankhede