Android
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()));
に変更したら、ちゃんと結果を受け取れるようになりました。