使用Mockito模拟AccountManager

维托尔维加诺

我正在使用Mockito模拟Activity测试中的AccountManager。

因此,我的测试代码如下:

public class PressuresListActivityUnitTest extends
    ActivityUnitTestCase<PressuresListActivity> {

// Test data.
private static final String ACCOUNT_TYPE = "com.example.android";
private static final Account ACCOUNT_1 = new Account("[email protected]", ACCOUNT_TYPE);
private static final Account ACCOUNT_2 = new Account("[email protected]", ACCOUNT_TYPE);
private static final Account[] TWO_ACCOUNTS = { ACCOUNT_1, ACCOUNT_2 };

@Mock
private AccountManager mMockAccountManager;

public PressuresListActivityUnitTest() {
    super(PressuresListActivity.class);
}

@Override
protected void setUp() throws Exception {
    super.setUp();

    setupDexmaker();
    // Initialize mockito.
    MockitoAnnotations.initMocks(this);
}

public void testAccountNotFound() {
    Mockito.when(mMockAccountManager.getAccounts())
            .thenReturn(TWO_ACCOUNTS);

    Intent intent = new Intent(Intent.ACTION_MAIN);
    startActivity(intent, null, null);
}

/**
 * Workaround for Mockito and JB-MR2 incompatibility to avoid
 * java.lang.IllegalArgumentException: dexcache == null
 *
 * @see <a href="https://code.google.com/p/dexmaker/issues/detail?id=2">
 *     https://code.google.com/p/dexmaker/issues/detail?id=2</a>
 */
private void setupDexmaker() {
    // Explicitly set the Dexmaker cache, so tests that use mockito work
    final String dexCache = getInstrumentation().getTargetContext().getCacheDir().getPath();
    System.setProperty("dexmaker.dexcache", dexCache);
}

以及将要测试的活动的onCreate方法:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_pressures_list);

    AccountManager am = AccountManager.get(this);
    Account[] accounts = am.getAccounts();
    if (accounts.length > 0) {
        Log.i("TAG", "it works!");
    }
}

但是,当我运行测试时,AccountManager.getAccounts不会返回测试中指定的帐户。

任何的想法?

维托尔维加诺

经过研究,我终于解决了这个问题。

Android提供了一些可在测试中使用的类,例如MockContext,IsolatedContext。

http://developer.android.com/reference/android/test/mock/MockContext.html

http://developer.android.com/reference/android/test/IsolatedContext.html

为完成此任务,我创建了ContextWrapper的子类并覆盖(??)getSystemService方法。

根据文档:

“仅将其所有调用委派给另一个Context的Context的代理实现。可以被子类化以修改行为,而无需更改原始Context。”

http://developer.android.com/reference/android/content/ContextWrapper.html

这样,我使用常规的AndroidActivityUnitTestCase在Activity内注入了原始上下文,但对其进行了修改以满足我的需要。

看一下这个:

public class FakeContextWrapper extends ContextWrapper {

    private static final String ACCOUNT_TYPE = "com.example.android";

    private static final Account ACCOUNT_1 = new Account("[email protected]", ACCOUNT_TYPE);
    private static final Account ACCOUNT_2 = new Account("[email protected]", ACCOUNT_TYPE);

    private static final Account[] TWO_ACCOUNTS = { ACCOUNT_1, ACCOUNT_2 };

    @Mock
    private AccountManager mMockAccountManager;

    public FakeContextWrapper(Context base) {
        super(base);

        MockitoAnnotations.initMocks(this);
        Mockito.when(mMockAccountManager.getAccounts()).thenReturn(TWO_ACCOUNTS);
    }

   @Override
   public Object getSystemService(String name) {
       if (Context.ACCOUNT_SERVICE.equals(name)) {
           return mMockAccountManager;
       } else {
           return super.getSystemService(name);
       }
   }
}

测试内:

public void testAccountNotFound() {
    Context context = new FakeContextWrapper(getInstrumentation().getTargetContext());
    setActivityContext(context);
    Intent intent = new Intent(Intent.ACTION_MAIN);
    startActivity(intent, null, null);
    // TODO assertions.
}

最后,要测试的活动:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_pressures_list);

    AccountManager am = AccountManager.get(this);
    Account[] accounts = am.getAccounts();
    if (accounts.length == 0) {
        // TODO call login.
    } else {
        Log.i("TAG", "it works!");
    }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章