我正在尝试测试在后台执行api请求并返回一些数据的异步任务。通过模拟器运行时一切运行正常,但是当我运行书面测试时,我得到NoClassDefFoundError
。它似乎引用的类是Google Cloud api类的构建器类。如果我注释掉api调用代码并返回一个硬编码的笑话,则测试通过。
在测试中是否还需要做其他事情来包含Google api库?
package com.udacity.gradle.builditbigger;
import android.test.AndroidTestCase;
import android.util.Log;
import org.chrisolsen.common.Joke;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class JokeTaskTest extends AndroidTestCase {
private static final String TAG = "JokeTaskTest";
private CountDownLatch signal = null;
@Override
protected void setUp() throws Exception {
Log.d(TAG, "setUp:");
signal = new CountDownLatch(1);
}
@Override
protected void tearDown() throws Exception {
signal.countDown();
}
public void testTheAsyncTask() throws Throwable {
final JokeTask task = new JokeTask(new JokeTask.JokeTaskListener() {
@Override
public void onJokeReceived(Joke joke) {
Log.d(TAG, "onJokeReceived: in the listeneer");
assertTrue(true);
signal.countDown();
}
});
task.execute();
signal.await(10, TimeUnit.SECONDS);
}
}
package com.udacity.gradle.builditbigger;
import android.os.AsyncTask;
import android.util.Log;
import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.extensions.android.json.AndroidJsonFactory;
import com.google.api.client.googleapis.services.AbstractGoogleClientRequest;
import com.google.api.client.googleapis.services.GoogleClientRequestInitializer;
import org.chrisolsen.backend.myApi.MyApi;
import org.chrisolsen.common.Joke;
import java.io.IOException;
public class JokeTask extends AsyncTask<Void, Void, Joke> {
public interface JokeTaskListener {
void onJokeReceived(Joke joke);
}
private static final String TAG = "JokeTask";
private JokeTaskListener mJokeListener;
private MyApi mApiService;
public JokeTask(JokeTaskListener listener) {
mJokeListener = listener;
}
@Override
protected Joke doInBackground(Void... voids) {
if(mApiService == null) { // Only do this once
// THIS IS WHERE --+ IT SEEMS TO FAIL
// V
MyApi.Builder builder = new MyApi.Builder(AndroidHttp.newCompatibleTransport(),
new AndroidJsonFactory(), null)
// options for running against local devappserver
// - 10.0.2.2 is localhost's IP address in Android emulator
// - turn off compression when running against local devappserver
.setRootUrl("http://10.0.2.2:8080/_ah/api/")
.setGoogleClientRequestInitializer(new GoogleClientRequestInitializer() {
@Override
public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest) throws IOException {
abstractGoogleClientRequest.setDisableGZipContent(true);
}
});
mApiService = builder.build();
}
try {
String text = mApiService.getJoke().execute().getData();
Log.d(TAG, "doInBackground: " + text);
return new Joke(text);
} catch (IOException e) {
Log.d(TAG, "fetch: " + e.getLocalizedMessage());
return null;
}
}
@Override
protected void onPostExecute(Joke joke) {
Log.d(TAG, "onPostExecute: JOKE: " + joke);
mJokeListener.onJokeReceived(joke);
}
}
FATAL EXCEPTION: AsyncTask #1
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:278)
at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
at java.util.concurrent.FutureTask.run(FutureTask.java:137)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:208)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
at java.lang.Thread.run(Thread.java:856)
Caused by: java.lang.NoClassDefFoundError: com.udacity.gradle.builditbigger.JokeTask$1
at com.udacity.gradle.builditbigger.JokeTask.doInBackground(JokeTask.java:33)
at com.udacity.gradle.builditbigger.JokeTask.doInBackground(JokeTask.java:16)
at android.os.AsyncTask$2.call(AsyncTask.java:264)
<!-- Include required permissions for Google Mobile Ads to run -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:name="android.support.multidex.MultiDexApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<!-- This meta-data tag is required to use Google Play Services. -->
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- Include the AdActivity configChanges and theme. -->
<activity
android:name="com.google.android.gms.ads.AdActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
android:theme="@android:style/Theme.Translucent" />
</application>
</manifest>
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "22.0.1"
defaultConfig {
applicationId "com.udacity.gradle.builditbigger"
minSdkVersion 15
targetSdkVersion 23
versionCode 1
versionName "1.0"
multiDexEnabled true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
dexOptions {
javaMaxHeapSize "4g"
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
// Added for AdMob
compile project(':common')
compile project(':android')
compile 'com.android.support:appcompat-v7:23.1.0'
compile 'com.google.android.gms:play-services:8.3.0'
compile 'com.android.support:multidex:1.0.0'
}