我正在使用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("account1@gmail.com", ACCOUNT_TYPE);
private static final Account ACCOUNT_2 = new Account("account2@gmail.com", 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不会返回测试中指定的帐户。
有什么想法吗?
答案 0 :(得分:2)
这不是mockito的工作方式。
import static org.mockito.Mockito.*;
...
public void testAccountNotFound() {
AccountManager am = mock(AccountManager.class);
when(am.getAccounts()).thenReturn(TWO_ACCOUNTS);
// this is how you unit test something
assertTrue(am.getAccounts().size == 2);
}
public void testMoreRealWorldExample() {
AccountManager am = mock(AccountManager.class);
when(am.getAccounts()).thenReturn(TWO_ACCOUNTS);
/* try and create an account; createNewAccount() will call
getAccounts() to find out how many accounts there already
are in the system, and due to the above injection, it would
think there are already two. Thus we can test to make sure
users cannot create three or more accounts.
*/
boolean accountCreated = am.createNewAccount();
// maximum two accounts are allowed, so this should return false.
assertFalse(accountCreated);
}
您无法直接使用mockito只是在对象中随意注入值,然后运行Activity
。 Mockito用于对您的对象进行单元测试,理想情况是对Android特定对象的引用最少,但有些引用是不可避免的。
请阅读the cookbook more closely,因为它非常详尽。
如果你想模拟和整个Activity
,你需要查看in to Robolectric
答案 1 :(得分:2)
Android提供了一些在测试中使用的类,如MockContext,IsolatedContext。
http://developer.android.com/reference/android/test/mock/MockContext.html
http://developer.android.com/reference/android/test/IsolatedContext.html
为了完成这项工作,我创建了ContextWrapper和overrode(??)getSystemService方法的子类。
根据文件:
&#34;代理Context的实现,简单地将其所有调用委托给另一个Context。可以进行子类化以修改行为而不更改原始上下文。&#34;
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("account1@gmail.com", ACCOUNT_TYPE);
private static final Account ACCOUNT_2 = new Account("account2@gmail.com", 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!");
}
}