Android Unit testing with AsyncTask - android

Hey everyone just getting started with Android testing and I am trying to test an async task. Here is the async task code. I am following this SO post Android AsyncTask testing with Android Test Framework. The runTestOnUiThread is not found in AndroidTestCase however. If I understand this correctly if its not run on the ui thread then the test finishes before the async task completes? Any help is greatly appreciated !
public class BackendTest extends AndroidTestCase {
private static MyApi myApiService = null;
private Context context;
public void testAsyncJoke () throws Throwable{
// create a signal to let us know when our task is done.
final CountDownLatch signal = new CountDownLatch(1);
final AsyncTask<Pair<Context, String>, Void, String> myTask = new AsyncTask<Pair<Context, String>, Void, String>() {
#Override
protected String doInBackground(Pair<Context, String>... params) {
if(myApiService == null) { // Only do this once
MyApi.Builder builder = new MyApi.Builder(AndroidHttp.newCompatibleTransport(), new AndroidJsonFactory(), null)
.setRootUrl("https://androidnanodegreprojectfour.appspot.com/_ah/api/");
myApiService = builder.build();
}
context = params[0].first;
String name = params[0].second;
try {
return myApiService.sayHi(name).execute().getData();
} catch (IOException e) {
return e.getMessage();
}
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
signal.countDown();
}
};
// Execute the async task on the UI thread! THIS IS KEY!
runTestOnUiThread(new Runnable() {
#Override
public void run() {
myTask.execute("Do something");
}
});
signal.await(30, TimeUnit.SECONDS);
// The task is done, and now you can assert some things!
assertTrue("Happiness", true);
}
}

Related

Syncronous API calls

I'm working on an Android app by adding a new functionality that fetch and save data with API calls.
These calls are made in a Fragment. There is a call made in an AsyncTask, and I don't want to create an AsyncTask for every call, so I just try send parameters to my controlles in some function, but when I debug every time I try to make a call without using an AsyncTask, I got an IOException "Cancelled". Is there a way to do this without using AsyncTasks in the same Fragment?
This is the AsyncTask:
private void validateUnit(#NonNull String unitCode, final int routeId, final boolean goodCondition) {
mUnitDetails = new UnitDetails();
if (mFindUnitAysncTask != null) {
mFindUnitAysncTask.cancel(true);
}
mFindUnitAysncTask = new AsyncTask<String, Void, FindUnitResponse>() {
#Override
protected void onPreExecute() {
super.onPreExecute();
showProgressDialog();
}
#Override
protected FindUnitResponse doInBackground(String... params) {
FindUnitResponse unitResponse = mUnitController.findUnit(params[0], routeId);
FindUnitDetailsResponse unitDetailsResponse = mUnitController.getUnitDetails(
unitResponse.getUnits().get(0), mUser);
if(unitDetailsResponse.isSuccess()) {
mUnitDetails.setBranchCode(unitDetailsResponse.getBranchCode());
mUnitDetails.setBranchName(unitDetailsResponse.getBranchName());
mUnitDetails.setCompanyId(unitDetailsResponse.getCompanyId());
mUnitDetails.setEconomicNumber(unitDetailsResponse.getEconomicNumber());
mUnitDetails.setFuelType(unitDetailsResponse.getFuelType());
mUnitDetails.setFuelTypeId(unitDetailsResponse.getFuelTypeId());
mUnitDetails.setFuelPrice(unitDetailsResponse.getFuelPrice());
mUnitDetails.setModel(unitDetailsResponse.getModel());
mUnitDetails.setBrand(unitDetailsResponse.getBrand());
mUnitDetails.setUnitType(unitDetailsResponse.getUnitType());
mUnitDetails.setRouteCode(unitDetailsResponse.getRouteCode());
mUnitDetails.setRealTrips(unitDetailsResponse.getRealTrips());
mUnitDetails.setMaximumMileageRange(unitDetailsResponse.getMaximumMileageRange());
}
else {
showMessage(unitDetailsResponse.getMessage());
}
return unitResponse;
}
#Override
protected void onPostExecute(FindUnitResponse response) {
super.onPostExecute(response);
dismissProgressDialog();
if (response != null && response.isSuccess()) {
//Unit unit = response.getUnits().get(0);
unit = response.getUnits().get(0);
finishChecklist(unit, goodCondition);
} else {
showMessage(response.getMessage());
saveChecklist();
}
}
#Override
protected void onCancelled() {
super.onCancelled();
dismissProgressDialog();
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, unitCode);
}
With that I fetch the details of a vehicle. Then I have a method called validateMileage.
private void validateMileage(#NonNull Unit unit, #NonNull User user, #NonNull int mileage, int travels,
final boolean dayFinished) {
List<Incident> incidents = mIncidentController.getIncidentList();
Incident suspiciousMileageIncident = mIncidents.get(2);
List<Manager> managers = mManagersController.findByIncidentId(suspiciousMileageIncident.getId());
.....
}
If I just try to make calls like .getIncidentsList or .findByIncidentId I got an IOException when I wait for the response. But if I make the call in an AsyncTask, there is not errors.

Null pointer exception running connected test in Android studio

I am trying to execute connected test for P4, however I am reciing an "Null pointer exception error" for P4
Error message:
:00:02 PM null
java.lang.NullPointerException
at com.android.ddmlib.Client.read(Client.java:692)
at com.android.ddmlib.MonitorThread.processClientActivity(MonitorThread.java:304)
at com.android.ddmlib.MonitorThread.run(MonitorThread.java:256)
It is a standard test, verifying non-empty string in the Async task
Test function:
public void runCloudModuleTest() {
String joke = null;
JokesAsyncTask jokesAsyncTask = new JokesAsyncTask(getContext(), null);
jokesAsyncTask.execute();
try {
joke = jokesAsyncTask.get();
Log.d("CloudModuleTest", "Retrieved a non-empty string successfully: " + joke);
} catch (Exception e) {
e.printStackTrace();
}
assertNotNull(joke);
}
Can someone help me understand what the issue is?
AsyncTask: The Async task pulls data from google cloud engine
public class JokesAsyncTask extends AsyncTask, Void, String> {
private static JokeApi myApiService = null;
private Context mContext;
private String mResult;
private ProgressBar mProgressBar;
public JokesAsyncTask(Context context, ProgressBar progressBar) {
this.mContext = context;
this.mProgressBar = progressBar;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
if (mProgressBar != null) {
mProgressBar.setVisibility(View.VISIBLE);
}
}
#Override
protected String doInBackground(Pair<Context, String>... pairs) {
if (myApiService == null) {
JokeApi.Builder builder = new JokeApi.Builder(AndroidHttp.newCompatibleTransport(),
new AndroidJsonFactory(), null)
.setRootUrl("https://testandroiddevelopment.appspot.com/_ah/api/");
myApiService = builder.build();
}
try {
return myApiService.sendJoke(new JokeBean()).execute().getJoke();
} catch (IOException e) {
return e.getMessage();
}
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (mProgressBar != null) {
mProgressBar.setVisibility(View.GONE);
}
mResult = result;
startJokeDisplayActivity();
}
private void startJokeDisplayActivity() {
Intent intent = new Intent(mContext, JokeViewActivity.class);
intent.putExtra(JokeViewActivity.JOKE_KEY, mResult);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);
}
}
I have referenced the variable and it is not an issue due due to the below post, however I did investigate and finally cleaned up and rebuild the project that helped resolved the issue
I have referenced the variable and it is not an issue due due to the post #AxelH, however I did investigate and finally cleaned up and rebuild the project that helped resolved the issue

doInBackground is not getting called sometimes Android

In my application, there are multiple asynctasks. Please let me know why doInBackground of an asynctask sometimes does not getting called. Its onPreExecute method gets called. Is there any issue because of multiple asynctasks or something else?
/* ASync class for test table */
public class TestAsynch extends AsyncTask<String, Void, String>{
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
String status = null;
String result1=API_Manager.getInstance().sendTestData(userName);
try {
if(result1 != null) {
// save in db
}
}
}
catch( Exception e) {
e.printStackTrace();
}
return status;
}
#Override
protected void onPostExecute(String status) {
}
}
If your project has multiple asynctasks you must check that there is a limit of asynctasks that can be executed. When you create a new AsyncTask it will be added on a Pool and will be execute only when is possible.
Check this answer:
Multitasking on android
And the docs: ThreadPoolExecutor
Here is an example on how properly handle multiple AsyncTasks AsyncTaskManager
OnPreExecute() gets called on the UI thread and doInBackground() is called on the background thread.
There is one dedicated background thread for the async task. This behaviour can be changed if you want to.
http://android-er.blogspot.in/2014/04/run-multi-asynctask-as-same-time.html
Now, say you have multiple instances of async task and I'm assuming you are calling execute() to run the async tasks. This will trigger all the preExecute immediately since UI thread is free but for the doInBackground it will triggered one by one. Hence it may take some time for the next async task to start.
doInBackground should run on a loop using a Boolean to check before execution. Before your Task is being executed, set a global boolean (may be true/false) depends on which you prefer and values add on thread should call runOnUiThread.
startExect = true;
new TestAsynch().execute();
then change this
public class TestAsynch extends AsyncTask<String, Void, String>{
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
String status = null;
String result1=API_Manager.getInstance().sendTestData(userName);
try {
if(result1 != null) {
// save in db
}
}
}
catch( Exception e) {
e.printStackTrace();
}
return status;
}
#Override
protected void onPostExecute(String status) {
}
}
to this
public class TestAsynch extends AsyncTask<String, Void, String> {
String result1 = null;
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
String status = null;
result1=API_Manager.getInstance().sendTestData(userName);
while (startExecute) {
Thread exe = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(5);
}
catch( Exception e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
#Override
public void run() {
if(result1 != null) {
// save in db
}
}
});
}
}); exe.start();
}
return status;
}
#Override
protected void onPostExecute(String status) {
}
}

Android with MobileServiceClient crashed on AsyncTask<Void, Void, Void>()

I've problem with:
public void GetNews() {
if (mClient == null) {
return;
}
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
try {
final List<News> results = newsTable.execute().get();
runOnUiThread(new Runnable() {
#Override
public void run() {
newsAdapter.clear();
for (News news : results) {
newsAdapter.add(news);
}
}
});
} catch (Exception e) {
createAndShowDialog(e, "Chyba");
}
return null;
}
}.execute();
}
App every crashed when executing this code :-(
Code get rows from table in azure mobile services.
Any ideas?
Without seeing your full code sample, my guess is that you've not initialized newsAdapter in a proper way and it is failing when adding there. Share your full code sample and error logs and I can try and be more specific.

How to Async Task Network Operation in Service in Android?

This is my Service which does network operation. But it is throwing NetworkonMainThreadException which i understand android upper version doesn't allows network operation under main thread. Now i want to use Async Task for this purpose. I am not sure which are all code i need to add under Async Task from Service Class to actually make the code complete. Below is my Service Code :
public class NewsTickerDataService extends Service {
#Override
public void onStart(Intent aIntent, int aStartId) {
super.onStart(aIntent, aStartId);
RemoteViews _views = buildUpdatedViews(this);
ComponentName _widget =
new ComponentName(this, NewsTicker.class);
AppWidgetManager _manager =
AppWidgetManager.getInstance(this);
_manager.updateAppWidget(_widget, _views);
}
#Override
public IBinder onBind(Intent aParamIntent) {
// not supporting binding
return null;
}
private RemoteViews buildUpdatedViews(Context aContext) {
List<Story> _stories = getStories();
RemoteViews _result = new RemoteViews(
aContext.getPackageName(),
R.layout.activity_main
);
if (_stories.isEmpty()) {
_result.setTextViewText(R.id.title,
"Sadly there's nothing to read today.");
} else {
_result.setTextViewText(
R.id.title, _stories.get(0).getTitle());
}
return _result;
}
private List<Story> getStories() {
try {
URL _url = new URL("http://search.twitter.com" +
"/search.atom?q=%23uml&" +
"result_type=mixed&count=5"
);
InputStream _in = _url.openStream();
return parse(new InputSource(_in));
} catch (Exception anExc) {
Log.e("NewsTicker", anExc.getMessage(), anExc);
return new ArrayList<Story>();
}
}
private List<Story> parse(InputSource aSource)
throws Exception {
SAXParserFactory _f = SAXParserFactory.newInstance();
SAXParser _p = _f.newSAXParser();
XMLReader _r = _p.getXMLReader();
AbstractParser _h = AbstractParser.newAtomParser();
_r.setContentHandler(_h);
_r.parse(aSource);
return _h.getStories();
}
}
Async Task Code :
public class YourAsyncTask extends AsyncTask<String, Void, String>{
#Override
protected String doInBackground(String... params) {
// your load work
//return myString;
}
#Override
protected void onPostExecute(String result) {
}
}
Can someone please help me to integrate Async Task into same code. Thanks
Yes, I'd suggest IntentService too!
IntentService example
public class MyService extends IntentService {
private int STOP_DOWNLOAD = false;
public static int UPDATE_PROGRESS = 0;
public MyService() {
super("myservice");
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
protected void onHandleIntent(Intent intent) {
// Network Task : download ?
// Send some data to the receiver
Bundle resultData = new Bundle();
resultData.putInt("progress", progress);
receiver.send("update", resultData);
}
private void stopDownload() {
this.STOP_DOWNLOAD = true;
// Stop the download : use this boolean into onHandleIntent
}
}
The receiver
public class MyReceiver extends ResultReceiver {
Context context;
public MyReceiver(Context mContext) {
super(handler);
context = mContext;
}
#Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
super.onReceiveResult(resultCode, resultData);
if (resultCode == "update") {
String something = resultData.getString(MyService.SOMETHING);
}
}
}
Start the service in an Activity : startService(...)
From the onStart() of your service class make network operation
YourAsyncTask.execute(url);
Async task code
public class YourAsyncTask extends AsyncTask<String, Void, String>{
#Override
protected String doInBackground(String... params) {
// your load work
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
response += s;
}
} catch (Exception e) {
e.printStackTrace();
}
return response;
//return myString;
}
#Override
protected void onPostExecute(String result) {
//HERE CALL YOUR PARSE METHOD
//AFTER PARSING CALL buildUpdatedViews(Context aContext , stories)
}
}

Categories

Resources