如何使用Mockito模拟SharedPreferences

时间:2016-01-30 18:39:10

标签: android sharedpreferences mockito

我刚读过Android中的单元检测测试,我想知道如何在没有任何SharedPreferencesHelper类的情况下模拟SharedPreferences,如here

我的代码是:

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;
}}

是否可以在不创建其他类的情况下模拟SharedPreferences?

3 个答案:

答案 0 :(得分:48)

所以,因为SharedPreferences来自你的context,所以很容易:

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

例如,对于getValidToken(Context context),测试可以是:

@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();
}

答案 1 :(得分:1)

还有一种更好的模拟SharedPreferences的方法,恕我直言。 我喜欢Mockito,但是在每个测试中模拟SharedPreferences都是徒劳的。

幸运的是,我们可以使用shared-preferences-mock库。该库在JVM上实现SharedPrefences,因此其行为类似于真实的类。而且,可以编写本地单元测试。

针对您的情况:

import com.github.ivanshafran.sharedpreferencesmock.SPMockBuilder;

class Test {
    private Context context;
    private SharedPreferences sharedPreferences;

    @Before
    public void setUp() {
        this.sharedPreferences = new SPMockBuilder().createSharedPreferences();
        this.context = Mockito.mock(Context.class);         
        Mockito.when(context.getSharedPreferences(Constants.LOGGED_USER_PREFERENCES,0))
            .thenReturn(sharedPreferences);
    }

    @Test
    public void test() {
        sharedPreferences.edit().putString(Constants.LOGGED_USERNAME, "admin").commit();
        String value = Auth.getLoggedUser(context);
        asssertEquals("admin", value);
    }

}

将其添加到存储库末尾的root build.gradle中:

allprojects {
    repositories {
        maven { url 'https://jitpack.io' }
    }
}

添加依赖项:

dependencies {
    testImplementation 'com.github.IvanShafran:shared-preferences-mock:1.0'
}

答案 2 :(得分:0)

以下示例显示了如何创建使用模拟Context对象(例如共享首选项)的单元测试。

@RunWith(MockitoJUnitRunner.class)
public class MProfileTest {

   @Mock
   Context mockContext;
   @Mock
   SharedPreferences mockPrefs;
   @Mock
   SharedPreferences.Editor mockEditor;

   @Before
   public void before() throws Exception {

      Mockito.when(mockContext.getSharedPreferences(anyString(), anyInt())).thenReturn(mockPrefs);
      Mockito.when(mockContext.getSharedPreferences(anyString(), anyInt()).edit()).thenReturn(mockEditor);

      Mockito.when(mockPrefs.getString("YOUR_KEY", null)).thenReturn("YOUR_VALUE");
   }

   @Test
   public void anyTest() {
      // Any shared preference you can call
      // Assert.assertTrue();
      String val = _mockPrefs.getString("YOUR_KEY", null); // It returns YOUR_VALUE
   }
}

如果您在导入模拟框架时遇到任何问题,只需确保已在app/build.gradle文件中添加了依赖关系。

https://developer.android.com/training/testing/unit-testing/local-unit-tests#setup


如果要通过将所有数据存储在内存中来使用真实的共享首选项作为设备,请遵循以下代码。

从此要旨https://gist.github.com/aslamanver/f74a2b3d450fda251d47a0d38b44edb7

中获取MockSharedPreference.java文件
@Mock
Context mockContext;

MockSharedPreference mockPrefs;
MockSharedPreference.Editor mockPrefsEditor;

@Before
public void before() {

    mockPrefs = new MockSharedPreference();
    mockPrefsEditor = mockPrefs.edit();

    Mockito.when(mockContext.getSharedPreferences(anyString(), anyInt())).thenReturn(mockPrefs);
}