我正在使用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] 删除。
我来说两句