NoClassDefFoundError, реализующий IdlingResource

Мне нужно сказать Espresso подождать, пока моя активность не будет простаивать. Для этого я использую интерфейс IdlingResource. Вот код, который я использую для тестирования:

    public class MyActivity extends Activity implements IdlingResource {

        private boolean isIdle;
        ResourceCallback resourceCallback;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_my);

            final Button myButton = (Button) findViewById(R.id.myButton);
            final ProgressBar progressBar = (ProgressBar) findViewById(R.id.progressBar);

            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    myButton.setVisibility(View.VISIBLE);
                    progressBar.setVisibility(View.GONE);
                    isIdle = true;
                }
            }, 3000);
        }

        public void ButtonClicked(View view) {
            Toast.makeText(MyActivity.this, "OK", Toast.LENGTH_SHORT).show();
        }

        @Override
        public String getName() {
            return getClass().getName();
        }

        @Override
        public boolean isIdleNow() {

            if(isIdle){
                resourceCallback.onTransitionToIdle();
                return true;
            }

            return false;
        }

        @Override
        public void registerIdleTransitionCallback(ResourceCallback resourceCallback) {
            this.resourceCallback = resourceCallback;
        }
    }

Espresso автоматически ожидает завершения AsyncTask, поэтому, если я использую AnsycTask, мне даже не нужно реализовывать этот интерфейс. Проблема в том, что я использую библиотеку для связи с сетью, и кажется, что она не использует AnsyncTasks или Espresso не знает об этом.

Моя проблема в том, что приведенный выше код отлично работает только на моем устройстве (Motorola XT1058 или Moto X), если я запускаю тот же тест на эмуляторе (Genymotion) или любом другом устройстве, я получаю следующее исключение:

junit.framework.AssertionFailedError: Exception in constructor: testA (java.lang.NoClassDefFoundError: rapnaveia.com.br.myapplication.MyActivity
at rapnaveia.com.br.myapplication.ApplicationTest.<init>(ApplicationTest.java:16)
at java.lang.reflect.Constructor.constructNative(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
at junit.runner.BaseTestRunner.getTest(BaseTestRunner.java:118)
at android.test.AndroidTestRunner.getTest(AndroidTestRunner.java:149)
at android.test.AndroidTestRunner.setTestClassName(AndroidTestRunner.java:57)
at android.test.suitebuilder.TestSuiteBuilder.addTestClassByName(TestSuiteBuilder.java:80)
at android.test.InstrumentationTestRunner.parseTestClass(InstrumentationTestRunner.java:443)
at android.test.InstrumentationTestRunner.parseTestClasses(InstrumentationTestRunner.java:424)
at android.test.InstrumentationTestRunner.onCreate(InstrumentationTestRunner.java:370)
at com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner.onCreate(GoogleInstrumentationTestRunner.java:114)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4435)
at android.app.ActivityThread.access$1300(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1316)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5103)
at java.lang.reflect.Method.invokeNative(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:191)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:176)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:554)
at com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner.onStart(GoogleInstrumentationTestRunner.java:167)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1701)

Вот код моего тестового класса:

public class ApplicationTest extends ActivityInstrumentationTestCase2<MyActivity> {

    public ApplicationTest() {
        super(MyActivity.class);
    }

    public void testA(){
        Espresso.registerIdlingResources(getActivity());
        Espresso.onView(withId(R.id.myButton)).perform(click());
    }
}

build.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 20
    buildToolsVersion "20.0.0"

    defaultConfig {
        applicationId "rapnaveia.com.br.myapplication"
        minSdkVersion 15
        targetSdkVersion 20
        versionCode 1
        versionName "1.0"

        testApplicationId 'br.com.rapnaveia'
        testInstrumentationRunner 'com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner'
    }
    buildTypes {
        release {
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile files('libs/espresso-1.1-bundled.jar')
}

person Androiderson    schedule 20.08.2014    source источник
comment
Версия Android одинакова на всех устройствах? Можете ли вы показать код для ActivityInstrumentationTestCase2?   -  person luiscosta    schedule 20.08.2014
comment
@Akagami это класс Android   -  person Androiderson    schedule 20.08.2014
comment
@ExceptionAl, можете ли вы предоставить содержимое файла gradle.build?   -  person Igor Castañeda Ferreira    schedule 20.08.2014
comment
@IgorCastañedaFerreira готово!   -  person Androiderson    schedule 20.08.2014


Ответы (1)


Проблема в конфигурации Gradle. Ваш проект пытается дважды скомпилировать банку эспрессо.

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile files('libs/espresso-1.1-bundled.jar')
}

В этой конфигурации банка эспрессо компилируется как вашим основным проектом, так и вашим тестовым проектом. Итак, когда вы пытаетесь выполнить тест, основной проект не собирается должным образом, что приводит к ошибке (и я думаю, что это странно, что вы можете запустить тест на своем устройстве).

Чтобы запустить ваши тесты, все, что вам нужно сделать, это удалить инструкцию компиляции из зависимости вашей тестовой цели.

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

Тестовый проект Android будет использовать банку эспрессо, скомпилированную в основном проекте, поскольку основной проект «скомпилирован» в тестовый проект.

person Igor Castañeda Ferreira    schedule 20.08.2014
comment
Это станет проще после реализации этой проблемы: code. google.com/p/android-test-kit/issues/detail?id=71 - person yogurtearl; 21.08.2014
comment
Должны ли мы использовать jar вместо зависимости от gradle? - person IgorGanapolsky; 30.12.2018
comment
@IgorGanapolsky На момент ответа да. В настоящее время нет больше этого жесткого ограничения. - person Igor Castañeda Ferreira; 24.01.2019