Android AsyncTaskのテストを行う
で検索すると、いろいろと記事が出てきますが、自分でも書いておいたほうがわかりやすいので、書いておきます。
//テスト対象のアクティビティ public class OfferDetailActivity extends UtilsActivity implements PostJsonTask.PostJsonTaskCallback, View.OnClickListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.offer_detail); context = this; user = getIntent().getParcelableExtra("user"); Bundle extras = getIntent().getExtras(); getmOfferId(extras); if (mOfferId != null) { HashMap<String, String> data = user.makeDataMap(); String jsonToServer = new Gson().toJson(data); PostJsonTask post_json_task = new PostJsonTask(context, jsonToServer, this); post_json_task.execute(AppConstants.OFFER_DETAIL_URL + "offer_id=" + mOfferId); } else { Toast.makeText(getApplicationContext(), "エラー パラメーターがありません", Toast.LENGTH_LONG).show(); } }
//テスト対象のAsyncTask public class PostJsonTask extends AsyncTask<String, Void, String> { final String TAG = "PostJsonTask"; Context localContext; private String jsonData = null; private PostJsonTaskListener mListener; private Exception mError = null; public PostJsonTask(Context context, String data, PostJsonTaskCallback _callback) { localContext = context; jsonData = data; this.callback = _callback; } private PostJsonTaskCallback callback; //Activiyへのコールバック用interface public interface PostJsonTaskCallback { void postJsonPreExecute(); void postJsonPostExecute(String result); void postJsonCancel(); } //テストコードのためだけに利用 public PostJsonTask(Context context, String data) { // Required by the semantics of AsyncTask super(); this.localContext = context; } @Override public void onPreExecute(){ super.onPreExecute(); if(callback != null) { callback.postJsonPreExecute(); } } @Override public String doInBackground(String... params) { String result = null; try { result = getJson(params[0]); } catch (RuntimeException e){ mError = e; } return result; } private String getJson(String address){ try { URL url = new URL(address); URLConnection conn = url.openConnection(); conn.setRequestMethod("POST"); conn.setInstanceFollowRedirects(false); conn.setRequestProperty("Accept-Language", "jp"); conn.setDoOutput(true); conn.setRequestProperty("Content-Type", "application/json; charset=utf-8"); OutputStream os = conn.getOutputStream(); PrintStream ps = new PrintStream(os); ps.print(jsonData); ps.close(); StringBuffer sb = new StringBuffer(); BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream())); String line = null; while ((line = br.readLine())!= null){ sb.append(line); } br.close(); return sb.toString(); } catch (MalformedURLException e) { e.printStackTrace(); throw new IllegalArgumentException("Invalid URL"); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException("Network error"); } } @Override public void onPostExecute(String result) { super.onPostExecute(result); Log.d(TAG, result); if(callback != null) { callback.postJsonPostExecute(result); } if (this.mListener != null) { this.mListener.onComplete(result, mError); } } @Override public void onCancelled() { super.onCancelled(); if(callback != null) { callback.postJsonCancel(); } if (this.mListener != null) { mError = new InterruptedException("AsyncTask cancelled"); this.mListener.onComplete(null, mError); } } //テストのために追加 public PostJsonTask setListener(PostJsonTaskListener listener) { this.mListener = listener; return this; } public static interface PostJsonTaskListener { public void onComplete(String jsonString, Exception e); } }
//テストコード public class GetOfferDetailJSONTest extends ActivityInstrumentationTestCase2 { String mJsonString = null; Exception mError = null; CountDownLatch signal = null; private Activity mActivity; private int mOfferId; private User mUser; private int TEST_OFFER_ID = 107; public GetOfferDetailJSONTest() { super(OfferDetailActivity.class); } @Override protected void setUp() throws Exception { signal = new CountDownLatch(1); mUser = new User.Builder("2", "sakurai", "123456", "", "", "", "", "", "","", 0, 0) .build(); mOfferId = TEST_OFFER_ID; mActivity = getActivity(); } @Override protected void tearDown() throws Exception { signal.countDown(); } public void testPreConditions(){ assertNotNull(mActivity); assertNotNull(mOfferId); assertNotNull(mUser); } public void testPostJsonTask() throws InterruptedException { HashMap<String, String> user_info = mUser.makeDataMap(); Context context = mActivity.getApplicationContext(); String jsonToServer = new Gson().toJson(user_info); String url = AppConstants.OFFER_DETAIL_URL + "offer_id=" + mOfferId; PostJsonTask task = new PostJsonTask(context, jsonToServer); task.setListener(new PostJsonTask.PostJsonTaskListener() { @Override public void onComplete(String jsonString, Exception e) { mJsonString = jsonString; mError = e; signal.countDown(); } }).execute(url); signal.await(); assertNull(mError); assertFalse(TextUtils.isEmpty(mJsonString)); assertTrue(mJsonString.startsWith("{ \"res\"")); assertTrue(mJsonString.endsWith("}")); } }
下記のブログを参考にさせて頂きました。m(_ _)m
http://marksunghunpark.blogspot.jp/2015/05/how-to-test-asynctask-in-android.html
ちなみに、はまっちゃったのはPostJsonTaskから、テストを実行すると何も帰ってこないということ。
理由はわかりませんでした。
しかし、すでにデプリケイトされたDefaultHttpClientを下記のように使っていたんですが
HttpClient client = new DefaultHttpClient(); HttpPost post = new HttpPost(params[0]);// in this case, params[0] is URL try { // set up post data StringEntity se = new StringEntity(jsonData, "UTF-8"); post.setEntity(se); post.setHeader("Accept", "application/json"); post.setHeader("Content-Type", "application/json");
//あとは省略
これをやめて、上記のように
URL url = new URL(address); URLConnection conn = url.openConnection(); StringBuffer sb = new StringBuffer(); BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
に変更したら、ちゃんと結果を受け取れるようになりました。