Using mockito to mock AccountManager - android

I'm using mockito to mock AccountManager inside an Activity test.
So, my test code is as follows:
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);
}
And the onCreate mthod of activity that will be tested:
#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!");
}
}
But when I run the test, AccountManager.getAccounts does NOT return the accounts specified in the test.
Any idea?

After some research, I finally solved the problem.
Android provides some classes to be used inside the tests, like MockContext, IsolatedContext.
http://developer.android.com/reference/android/test/mock/MockContext.html
http://developer.android.com/reference/android/test/IsolatedContext.html
To get this done, I created a subclass of ContextWrapper and overrode(??) getSystemService method.
According to the documentation:
"Proxying implementation of Context that simply delegates all of its calls to another Context. Can be subclassed to modify behavior without changing the original Context."
http://developer.android.com/reference/android/content/ContextWrapper.html
This way, I injected the original context, but modified to fit my needs, inside the Activity using a regular AndroidActivityUnitTestCase.
Check this out:
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);
}
}
}
Inside the test:
public void testAccountNotFound() {
Context context = new FakeContextWrapper(getInstrumentation().getTargetContext());
setActivityContext(context);
Intent intent = new Intent(Intent.ACTION_MAIN);
startActivity(intent, null, null);
// TODO assertions.
}
Finally, the Activity under test:
#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!");
}
}

That's not how mockito works.
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);
}
You can't directly use mockito to just arbitrarily inject values in objects and then run an Activity. Mockito is for unit testing your objects, ideally with minimal references to Android-specific objects, though some references will be inevitable.
Please read the cookbook more closely as it is pretty thorough.
If you want to mock and entire Activity, you'll need to look in to Robolectric

Related

Unit Testing for private member List<Integer> mTasks in android

I am trying to write unit test cases for below class. Specially, for 'isSumOfTaskWeightIsValid()' method from the below. it has private member involved it. Could you please help writing test cases for that. I find it difficult because of the 'for loop' in that method where it loops over the 'mTasks'. Thanks in advance.
Class TaskCard {
private List<Integer> mTasks = new ArrayList<>();
private boolean mIsGood;
public TaskCard(boolean isGood) { mIsGood = isGood}
public void setUpListofTasks(DataBaseHelper db){
mTasks.addAll(db.getTasks());
}
public boolean isSumOfTaskWeightIsValid(){
int sum = 0;
for(int taskWeight : mTasks)
{ sum += taskWeight;
}
return (sum>0 || mIsGood);
}
}
You can use #Before annotation to fill your mTasks list and then you can call your isSumOfTaskWeightIsValid method. You also need set your mIsGood parameter in your constructor. Here is a sample test class.
private TaskCard taskCard;
#Before
public void initObjects() {
taskCard = new TaskCard(...); //True or False
//Initialize DataBaseHelper here
DataBaseHelper db = new DataBaseHelper();
taskCard.setUpListofTasks(db);
}
#Test
public void testIsSumOfTaskWeightIsValid() {
// Now your list is filled with the value you prove in #Before
assertTrue(taskCard.isSumOfTaskWeightIsValid());
}

Android binding and JUnit testing of notification

I want to test my Android view models. Especially when the setter should notify about changes or not.
The view model looks like this (with more bindable properties):
public class EditViewModel extends BaseObservable {
private String _comment;
#Bindable
public String getComment() {
return _comment;
}
public void setComment(String comment) {
if (_comment == null && comment == null) {
// No changes, both NULL
return;
}
if (_comment != null && comment != null && _comment.equals(comment)) {
//No changes, both equals
return;
}
_comment = comment;
// Notification of change
notifyPropertyChanged(BR.comment);
}
}
In my UnitTest I register a listener, to get the notifications and track them with a following class:
public class TestCounter {
private int _counter = 0;
private int _fieldId = -1;
public void increment(){
_counter++;
}
public int getCounter(){
return _counter;
}
public void setFieldId(int fieldId){
_fieldId = fieldId;
}
public int getFieldId(){
return _fieldId;
}
}
So my test methods looks like the following:
#Test
public void setComment_RaisePropertyChange() {
// Arrange
EditViewModel sut = new EditViewModel(null);
sut.setComment("One");
final TestCounter pauseCounter = new TestCounter();
// -- Change listener
sut.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() {
#Override
public void onPropertyChanged(Observable sender, int propertyId) {
pauseCounter.increment();
pauseCounter.setFieldId(propertyId);
}
});
String newComment = "two";
// Act
sut.setComment(newComment);
// Assert
assertThat(pauseCounter.getCounter(), is(1));
assertThat(pauseCounter.getFieldId(), is(BR.comment));
assertThat(sut.getComment(), is(newComment));
}
If I execute the test methods alone, this approach works well. If I execute all tests at one, some fail, that the notification was 0 times called. I think, that the assertions is called before the callback could be handled.
I tried already following approches:
(1) Mock the listener with mockito as described in https://fernandocejas.com/2014/04/08/unit-testing-asynchronous-methods-with-mockito/.
#Test
public void setComment_RaisePropertyChange() {
// Arrange
EditViewModel sut = new EditViewModel(null);
sut.setComment("One");
Observable.OnPropertyChangedCallback listener = mock(Observable.OnPropertyChangedCallback.class);
// -- Change listener
sut.addOnPropertyChangedCallback(listener);
String newComment = "two";
// Act
sut.setComment(newComment);
// Assert
verify(listener, timeout(500).times(1)).onPropertyChanged(any(Observable.class), anyInt());
}
(2) Tried to use CountDownLatch as described in several SO answers.
None of them helped me. What can I do to be able to test the binding notification?
Your tests are working as a local unit tests in a sample project (link to GitHub repo here). I cannot reproduce the errors you are getting. A working rough example of a test class complete with imports is as follows - it generates 100% code coverage of your EditViewModel:
import android.databinding.Observable;
import org.junit.Test;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
public class EditViewModelTest {
#Test
public void setNewNonNullCommentRaisesPropertyChange() {
// Arrange
EditViewModel sut = new EditViewModel(null);
sut.setComment("One");
Observable.OnPropertyChangedCallback listener = mock(Observable.OnPropertyChangedCallback.class);
sut.addOnPropertyChangedCallback(listener);
String newComment = "two";
// Act
sut.setComment(newComment);
// Assert
verify(listener).onPropertyChanged(sut, BR.comment);
}
#Test
public void setNewNullCommentRaisesPropertyChange() {
// Arrange
EditViewModel sut = new EditViewModel(null);
sut.setComment("One");
Observable.OnPropertyChangedCallback listener = mock(Observable.OnPropertyChangedCallback.class);
sut.addOnPropertyChangedCallback(listener);
String newComment = null;
// Act
sut.setComment(newComment);
// Assert
verify(listener).onPropertyChanged(sut, BR.comment);
}
#Test
public void setEqualCommentDoesntRaisePropertyChange() {
// Arrange
EditViewModel sut = new EditViewModel(null);
sut.setComment("One");
Observable.OnPropertyChangedCallback listener = mock(Observable.OnPropertyChangedCallback.class);
sut.addOnPropertyChangedCallback(listener);
String newComment = "One";
// Act
sut.setComment(newComment);
// Assert
verify(listener, never()).onPropertyChanged(sut, BR.comment);
}
#Test
public void setNullToNullDoesntRaisePropertyChange() {
// Arrange
EditViewModel sut = new EditViewModel(null);
sut.setComment(null);
Observable.OnPropertyChangedCallback listener = mock(Observable.OnPropertyChangedCallback.class);
sut.addOnPropertyChangedCallback(listener);
String newComment = null;
// Act
sut.setComment(newComment);
// Assert
verify(listener, never()).onPropertyChanged(sut, BR.comment);
}
}
To diagnose the problem you are having, please make sure you have the correct dependencies as below:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile "org.mockito:mockito-core:+"
androidTestCompile "org.mockito:mockito-android:+"
}
The older setup with mockito and dexmaker is no longer valid. The most current versions of Mockito can be found on Maven Central
Also please check you are writing a local unit test in test rather than an instrumented test in androidTest - see this question for the difference.
Furthermore, such scenarios with complex logic inside a ViewModel are often better tested by extracting a helper object, making the object a dependency for the ViewModel passed inside the constructor, and testing against the helper object rather than against the ViewModel itself.
This may seem counter-intuitive because we are trained to think of Models as data objects with no dependencies. However, a ViewModel is more than a mere Model - often it ends up taking responsibilities of conversion of both model to view and view to model as in the discussion here.
Assume you have a tested class MyDateFormat with a unit test against it somewhere else in your project. You can now write a ViewModel that depends on it like this:
public class UserViewModel extends BaseObservable {
private final MyDateFormat myDateFormat;
#Nullable private String name;
#Nullable private Date birthDate;
public ProfileViewModel(#NonNull MyDateFormat myDateFormat) {
this.myDateFormat = myDateFormat;
}
#Bindable
#Nullable
public String getName() {
return name;
}
#Bindable
#Nullable
public String getBirthDate() {
return birthDate == null ? null : myDateFormat.format(birthDate.toDate());
}
public void setName(#Nullable String name) {
this.name = name;
notifyPropertyChanged(BR.name);
}
public void setBirthDate(#Nullable Date birthDate) {
this.birthDate = birthDate;
notifyPropertyChanged(BR.birthDate);
}
}

Android - How can I mock a lack of camera when testing my app?

I would like to check that my app shows an error message when the device it is running on has no camera. I have tried passing in a mock context but mockito gives an error when I try to mock the CameraManager class as it is declared final. Surely android has a simple solution for this? Here's my attempt:
public class CreateNewIdentityActivityUnitTest extends ActivityUnitTestCase<CreateNewIdentityActivity> {
public CreateNewIdentityActivityUnitTest() {
super(CreateNewIdentityActivity.class);
}
public void testErrorMessageDisplayedWhenNoCamerasExist() throws Exception {
// Create the mock cameramanager
// THIS LINE FAILS BECAUSE CAMERAMANAGER IS FINAL
CameraManager mockCameraManager = mock(CameraManager.class);
String[] cameraIdList = {};
when(mockCameraManager.getCameraIdList()).thenReturn(cameraIdList);
// Create the mock context
Context mockContext = mock(Context.class);
when(mockContext.getSystemService(Context.CAMERA_SERVICE)).thenReturn(mockCameraManager);
// Start the activity
Intent intent = new Intent(mockContext, CreateNewIdentityActivity.class);
Activity activity = startActivity(intent, null, null);
// Verify that the error message was made visible
TextView errorTextView = (TextView)activity.findViewById(R.id.ErrorTextView);
assertNotNull(errorTextView);
assertEquals(View.VISIBLE, errorTextView.getVisibility());
}
}
Unfortunately, you can't mock final class.
There're few options/hacks:
Try to add Robolectric library and write test with it's ShadowCamera
Move logic related to CameraManager into a separate class and inject it in Activity. Then in the Test project, you can override this injection.
Pretty similar idea - create an interface OnCameraManagerInterface
public interface OnCameraManagerInterface {
String[] getListOfCameras() throws CameraAccessException;
}
Then implement it in the Activity:
public class CreateNewIdentityActivity extends AppCompatActivity
implements OnCameraManagerInterface {
.......
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
#Override
public String[] getListOfCameras() throws CameraAccessException {
return ((CameraManager)getSystemService(Context.CAMERA_SERVICE)).
getCameraIdList();
}
}
And in the code, where you check camera existence - call: if (getListOfCameras().length == 0) {}
Now, add new TestCreateNewIdentityActivity to override your CreateNewIdentityActivity:
public class TestCreateNewIdentityActivity extends CreateNewIdentityActivity {
#Override
public String[] getListOfCameras() throws CameraAccessException {
return new String[0];
}
}
In Manifest:
<activity android:name=".TestCreateNewIdentityActivity"
android:theme="#style/AppTheme.NoActionBar"/>
And test will look like:
public class CreateNewIdentityActivityUnitTest extends ActivityUnitTestCase<TestCreateNewIdentityActivity> {
public CreateNewIdentityActivityUnitTest() {
super(TestCreateNewIdentityActivity.class);
}
public void testErrorMessageDisplayedWhenNoCamerasExist() throws Exception {
// Verify that the error message was made visible
TextView errorTextView = (TextView)getActivity().findViewById(R.id.ErrorTextView);
assertNotNull(errorTextView);
assertEquals(View.VISIBLE, errorTextView.getVisibility());
}
}
I'm pretty sure, it doable even without adding the TestActivity into the main source code and to manifest(to keep it in androidTest, though I didn't look)
Hybrid variant without creation of new activity:
public class ActivityCameraManager {
private boolean isTest = false;
private CameraManager cameraManager;
public ActivityCameraManager(CameraManager cameraManager) {
this.cameraManager = cameraManager;
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public String[] getListOfCameras() throws CameraAccessException {
if (isTest) {
return new String[0];
}
return cameraManager.getCameraIdList();
}
public void setTestMode() {
isTest = true;
}
}
Then your activity is gonna look like:
public class MainActivity extends AppCompatActivity {
ActivityCameraManager activityCameraManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
activityCameraManager = new ActivityCameraManager((CameraManager) getSystemService(Context.CAMERA_SERVICE));
}
public void setActivityCameraManagerForTest() {
activityCameraManager.setTestMode();
}
}
And in test just call getActivity().setActivityCameraManagerForTest();
I hope, it helps
The answer is late but here is a mock camera example for Android.
You can set the VideoFileInputSource to mock camera from video file
textureVideoInputSource = new VideoFileInputSource(this, "mock_input_video.mp4");
or you can enable hardware camera for video stream.
textureVideoInputSource = new CameraTextureVideoInputSource(this);
You can refer the answer here.
https://stackoverflow.com/a/38456189/1053097

How to implement AccountManager in my app

I try to implement an account manager in my app to avoid that the user has to log in each time he opens the app.
So basically, I already have my Authentication Activity where the user can put its login and password and where we receive a token from the server (the authentication is basic for now). Now I want to add the AccountManager but I don't really understand which part would go where.
What I need is pretty basic:
add an account if I never logged in before
log automatically if my account exists
if the auto authentication doesn't work get a new token on the server
Here is my code :
AuthenticationActivity.java
public class AuthenticationActivity extends Activity {
private EditText editTextUsername;
private EditText editTextPassword;
private Button buttonLogin;
private ProgressBar spinner;
private TextView error;
private TextView register;
private boolean accountRegistred;
AccountManager accountManager;
public static final String AUTHENTICATION = "authentication"; //action
private ConnectionSuccessReceiver connectionSuccessReceiver = new ConnectionSuccessReceiver();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.authentification);
accountManager = AccountManager.get(this);
Account[] accounts = accountManager.getAccountsByType("login");
if (accounts.length > 0) {
//If there is an account
} else {
accountRegistred = false;
editTextUsername = (EditText) findViewById(R.id.editText_login);
editTextUsername.setVisibility(View.VISIBLE);
editTextPassword = (EditText) findViewById(R.id.editText_password);
editTextPassword.setVisibility(View.VISIBLE);
buttonLogin = (Button) findViewById(R.id.button_connection);
buttonLogin.setVisibility(View.VISIBLE);
error = (TextView) findViewById(R.id.textView_error);
register = (TextView) findViewById(R.id.textView_register);
register.setVisibility(View.VISIBLE);
spinner = (ProgressBar) findViewById(R.id.progressBar);
buttonLogin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//Here we start the service which will reach the server
Intent i = new Intent(getApplicationContext(), AuthenticationService.class);
i.putExtra("username", editTextUsername.getText().toString());
i.putExtra("password", editTextPassword.getText().toString());
getApplication().startService(i);
spinner.setVisibility(View.VISIBLE);
error.setVisibility(View.INVISIBLE);
}
});
register.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
startActivity(new Intent(AuthenticationActivity.this, RegisterActivity.class));
}
});
}
registerReceiver(connectionSuccessReceiver, new IntentFilter(AUTHENTICATION));
}
private class ConnectionSuccessReceiver extends BroadcastReceiver {
//Called when the server returns success after authentication, we get the TOKEN here
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getStringExtra("STATE").equals("CONNECTED")) {
Intent i = new Intent(AuthenticationActivity.this, MainActivity.class);
i.putExtra("TOKEN", intent.getStringExtra("TOKEN"));
startActivity(i);
} else {
spinner.setVisibility(View.INVISIBLE);
error.setVisibility(View.VISIBLE);
}
finish();
}
}
#Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(connectionSuccessReceiver);
}
}
AuthenticatorService.java
public class AuthenticatorService extends Service {
/**
* The implementation of the class |AccountAuthenticatorImpl|.
* It is implemented as a singleton
*/
private static AccountAuthenticator accountAuthenticator = null;
/**
* The main constructor.
*/
public AuthenticatorService() {
super();
}
/**
* The bind method of the service.
* #param intent The intent used to invoke the service
* #return The binder of the class which has implemented |AbstractAccountAuthenticator|
*/
#Override
public IBinder onBind(Intent intent) {
IBinder ret = null;
if (intent.getAction().equals(android.accounts.AccountManager.ACTION_AUTHENTICATOR_INTENT)) {
ret = getAuthenticator().getIBinder();
}
return ret;
}
/**
* The method used to obtain the authenticator. It is implemented as a singleton
* #return The implementation of the class |AbstractAccountAuthenticator|
*/
private AccountAuthenticator getAuthenticator() {
if (AuthenticatorService.accountAuthenticator == null) {
AuthenticatorService.accountAuthenticator = new AccountAuthenticator(this);
}
return AuthenticatorService.accountAuthenticator;
}
public class AccountAuthenticator extends AbstractAccountAuthenticator {
private Context context;
public AccountAuthenticator(Context context) {
super(context);
this.context = context;
}
#Override
public Bundle editProperties(AccountAuthenticatorResponse accountAuthenticatorResponse, String s) {
return null;
}
#Override
public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options) throws NetworkErrorException {
Bundle reply = new Bundle();
Intent i = new Intent(context, AuthenticationActivity.class);
i.setAction("com.readyo.app.authentication.addnewaccount");
i.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
i.putExtra("AuthTokenType", authTokenType);
reply.putParcelable(AccountManager.KEY_INTENT, i);
return reply;
}
#Override
public Bundle confirmCredentials(AccountAuthenticatorResponse accountAuthenticatorResponse, Account account, Bundle bundle) throws NetworkErrorException {
return null;
}
#Override
public Bundle getAuthToken(AccountAuthenticatorResponse accountAuthenticatorResponse, Account account, String s, Bundle bundle) throws NetworkErrorException {
return null;
}
#Override
public String getAuthTokenLabel(String s) {
return null;
}
#Override
public Bundle updateCredentials(AccountAuthenticatorResponse accountAuthenticatorResponse, Account account, String s, Bundle bundle) throws NetworkErrorException {
return null;
}
#Override
public Bundle hasFeatures(AccountAuthenticatorResponse accountAuthenticatorResponse, Account account, String[] strings) throws NetworkErrorException {
return null;
}
}
}
I have also code to reach the server via HTTP but I'm not sure it would be important here.
Thank you for your time.
It's a bit late response but maybe this sample could help you:
https://github.com/dawidgdanski/AccountAuthenticatorExample
I created it some time ago but the logic with signing up/logging in may be helpful
add an account if I never logged in before:
If your app flow requires user to log in order to gain access to the data, then simply declare your LoginActivity as the primary one to be displayed.
Once you validate and verify user credentials, call AccountManager.addAccountExcplicitly() method.
On the other hand, if you expose some screens to be seen for anonymous users then in the application part (settings or whatever) where you provide login/sign up functionality call AccountManager.addAccount(). This call activates your AccountAuthenticator that processes your request in YourAccountAuthenticator.addAccount() and may display LoginActivity/SignUpActivity according to your needs.
Please, bear in mind that you may create app-specific account from System Settings as well.
log automatically if my account exists
Well, I'm not sure whether I understand your demand correctly. Once you store Account in AccountManager's meta data it is available once you call AccountManager.getAccountsByType("my.account.type").
If you want to log in automatically then you must somewhere store your credentials which is obviously under the threat of sensitive data leak.
if the auto authentication doesn't work get a new token on the server
There is an AccountManager.invalidateAuthToken() method that removes currently stored authToken and calls for another one.
You can launch the example app, I think it may solve at least some of your problems because it covers the following logic:
login/signup
auth token invalidation
displaying currently logged accounts
logout
Cheers

android junit test google sample code

I have downloaded this code from developer.android
public class SpinnerTestActivity extends
ActivityInstrumentationTestCase2<SpinnerActivity> {
private SpinnerActivity mActivity;
private Spinner mSpinner;
private SpinnerAdapter mPlanetData;
public static final int ADAPTER_COUNT = 9;
public static final int INITIAL_POSITION = 0;
public static final int TEST_POSITION = 5;
private String mSelection;
private int mPos;
public SpinnerTestActivity() {
super("com.android.example.spinner", SpinnerActivity.class);
} // end of SpinnerActivityTest constructor definition
#Override
protected void setUp() throws Exception {
super.setUp();
setActivityInitialTouchMode(false);
mActivity = getActivity();
mSpinner = (Spinner) mActivity
.findViewById(com.android.example.spinner.R.id.Spinner01);
mPlanetData = mSpinner.getAdapter();
} // end of setUp() method definition
public void testPreConditions() {
assertTrue(mSpinner.getOnItemSelectedListener() != null);
assertTrue(mPlanetData != null);
assertEquals(mPlanetData.getCount(), ADAPTER_COUNT);
} // end of testPreConditions() method definition
public void testSpinnerUI() {
mActivity.runOnUiThread(new Runnable() {
public void run() {
mSpinner.requestFocus();
mSpinner.setSelection(INITIAL_POSITION);
} // end of run() method definition
} // end of anonymous Runnable object instantiation
); // end of invocation of runOnUiThread
this.sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
for (int i = 1; i <= TEST_POSITION; i++) {
this.sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
} // end of for loop
this.sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
mPos = mSpinner.getSelectedItemPosition();
mSelection = (String) mSpinner.getItemAtPosition(mPos);
TextView resultView = (TextView) mActivity
.findViewById(com.android.example.spinner.R.id.SpinnerResult);
String resultText = (String) resultView.getText();
assertEquals(resultText, mSelection);
}
}
My question is: How the testSpinnerUI is invoked? From where? I have read the junit documentation but cannot figure out.. Thanks!
Stupid question, though. I found the answer in this blog.
The lifecycle of a test case is basically this: construction, setUp(), tests run, tearDown(), and destruction. The setUp() method is used to do any general initialization used by all of specific tests. Each test to be run in the test case is implemented as its own method, where the method name begins with “test”. The tearDown() method is then used to uninitialize any resources acquired by the setUp() method.
Each specific test will have it’s own method beginning with “test” – the “test” method name prefix is case sensitive!
My initial question was how the test method ran, since no one is calling it. But from the above test each method should sart with test, so as to be identified.

Categories

Resources