Я пытаюсь настроить кинжал на своих инструментальных тестах эспрессо, чтобы издеваться над внешними ресурсами (в этом случае RESTful-сервисы). Образец, который я последовал в Robolectric для моего модульного тестирования, заключался в расширении моего класса Application Application и переопределении модулей Dagger с помощью тестовых модулей, которые возвратят насмешки. Я пытаюсь сделать то же самое здесь, но я получаю ClassCastException в своих тестах Espresso, когда пытаюсь применить приложение к своему пользовательскому приложению.Могу ли я расширить пользовательское приложение в Espresso?
Вот мой набор до сих пор:
Производство
Под приложение/SRC/главная/Java/COM/MyPackage/инъекции у меня есть:
MyCustomApplication
package com.mypackage.injection;
import android.app.Application;
import java.util.ArrayList;
import java.util.List;
import dagger.ObjectGraph;
public class MyCustomApplication extends Application {
protected ObjectGraph graph;
@Override
public void onCreate() {
super.onCreate();
graph = ObjectGraph.create(getModules().toArray());
}
protected List<Object> getModules() {
List<Object> modules = new ArrayList<Object>();
modules.add(new AndroidModule(this));
modules.add(new RemoteResourcesModule(this));
modules.add(new MyCustomModule());
return modules;
}
public void inject(Object object) {
graph.inject(object);
}
}
которые я использую следующим образом:
BaseActivity
package com.mypackage.injection.views;
import android.app.Activity;
import android.os.Bundle;
import com.mypackage.injection.MyCustomApplication;
public abstract class MyCustomBaseActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((MyCustomApplication)getApplication()).inject(this);
}
}
активность тестируемой
package com.mypackage.views.mydomain;
// imports snipped for bevity
public class MyActivity extends MyBaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//snip
}
}
Эспрессо Настройка
Под приложение/SRC/androidTest/Java/COM/MyPackage/инъекции у меня есть:
MyCustomEspressoApplication
package com.mypackage.injection;
import java.util.ArrayList;
import java.util.List;
import dagger.ObjectGraph;
public class MyCustomEspressoApplication extends MyCustomApplication {
private AndroidModule androidModule;
private MyCustomModule myCustomModule;
private EspressoRemoteResourcesModule espressoRemoteResourcesModule;
@Override
public void onCreate() {
super.onCreate();
graph = ObjectGraph.create(getModules().toArray());
}
protected List<Object> getModules() {
List<Object> modules = new ArrayList<Object>();
modules.add(getAndroidModule());
modules.add(getEspressoRemoteResourcesModule());
modules.add(getMyCustomModule());
return modules;
}
public void inject(Object object) {
graph.inject(object);
}
public AndroidModule getAndroidModule() {
if (this.androidModule == null) {
this.androidModule = new AndroidModule(this);
}
return this.androidModule;
}
public MyCustomModule getMyCustomModule() {
if (this.myCustomModule == null) {
this.myCustomModule = new MyCustomModule();
}
return this.myCustomModule;
}
public EspressoRemoteResourcesModule getEspressoRemoteResourcesModule() {
if (this.espressoRemoteResourcesModule == null) {
this.espressoRemoteResourcesModule = new EspressoRemoteResourcesModule();
}
return this.espressoRemoteResourcesModule;
}
}
Мой тест Эспрессо под приложение/SRC/androidTest/ком/MyPackage/эспрессо:
package com.mypackage.espresso;
// imports snipped for brevity
@RunWith(AndroidJUnit4.class)
@LargeTest
public class MyActivityTest extends ActivityInstrumentationTestCase2<MyActivity>{
private MyActivity myActivity;
public MyActivityTest() {
super(MyActivity.class);
}
@Before
public void setUp() throws Exception {
super.setUp();
injectInstrumentation(InstrumentationRegistry.getInstrumentation());
myActivity = getActivity();
}
@After
public void tearDown() throws Exception {
super.tearDown();
}
@Test
public void testWhenTheActionBarButtonIsPressedThenThePlacesAreListed() {
//The next line is where the runtime exception occurs.
MyCustomEspressoApplication app = (MyCustomEspressoApplication)getInstrumentation().getTargetContext().getApplicationContext();
//I've also tried getActivity().getApplication() and
// getActivity.getApplicationContext() with the same results
//snip
}
}
Мои AndroidManifest.xml
(я видел много ответов в отношении ClassCastException в пользовательских классах приложений раньше, и большинство из них указывают на отсутствие свойства «android: name» на узле Application. Я вставив это здесь, чтобы показать, что это не так, насколько я могу сказать)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.mypackage">
<!-- snip -->
<application
android:name=".injection.MyCustomApplication"
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<!-- snip -->
</application>
<!-- snip -->
</manifest>
build.gradle
buildscript {
repositories {
mavenCentral()
jcenter()
}
}
apply plugin: 'com.android.application'
apply plugin: 'idea'
android {
testOptions {
unitTests.returnDefaultValues = true
}
lintOptions {
abortOnError false
}
packagingOptions {
exclude 'LICENSE.txt'
exclude 'META-INF/LICENSE'
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/NOTICE'
}
compileSdkVersion 21
buildToolsVersion "21.1.2"
defaultConfig {
applicationId "com.mypackage"
minSdkVersion 15
targetSdkVersion 21
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
}
idea {
module {
testOutputDir = file('build/test-classes/debug')
}
}
dependencies {
compile project(':swipeablecardview')
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:support-annotations:21.0.3'
compile 'com.android.support:appcompat-v7:21.0.3'
compile 'com.squareup:javawriter:2.5.0'
compile ('com.squareup.dagger:dagger:1.2.2') {
exclude module: 'javawriter'
}
compile ('com.squareup.dagger:dagger-compiler:1.2.2') {
exclude module: 'javawriter'
}
compile 'com.melnykov:floatingactionbutton:1.1.0'
compile 'com.android.support:cardview-v7:21.0.+'
compile 'com.android.support:recyclerview-v7:21.0.+'
// compile 'se.walkercrou:google-places-api-java:2.1.0'
compile 'org.apache.httpcomponents:httpclient-android:4.3.5.1'
compile 'commons-io:commons-io:1.3.2'
testCompile 'org.hamcrest:hamcrest-integration:1.3'
testCompile 'org.hamcrest:hamcrest-core:1.3'
testCompile 'org.hamcrest:hamcrest-library:1.3'
testCompile('junit:junit:4.12')
testCompile 'org.mockito:mockito-core:1.+'
testCompile('org.robolectric:robolectric:3.0-SNAPSHOT')
testCompile('org.robolectric:shadows-support-v4:3.0-SNAPSHOT')
androidTestCompile 'org.mockito:mockito-core:1.+'
androidTestCompile('com.android.support.test.espresso:espresso-core:2.0') {
exclude group: 'javax.inject'
exclude module: 'javawriter'
}
androidTestCompile('com.android.support.test:testing-support-lib:0.1')
}
StackTrace:.
java.lang.ClassCastException: com.mypackage.injection.MyCustomApplication не может быть отлита до com.mypackage.injection.MyCustomEspressoApplication на com.mypackage.espresso.MyActivityTest.testWhenTheActionBarButtonIsPressedThenThePlacesAreListed (MyActivityTest.java:107) на java.lang.reflect.Method.invokeNative (нативный метод) при java.lang.reflect.Method.invoke (Method.java:511) на org.junit.runners.model.FrameworkMethod $ 1.runReflectiveCall (FrameworkMethod.java:45) на org.junit.internal.runners.model.ReflectiveCallable.run (ReflectiveCallable.java:15) на org.junit.runners.model.FrameworkMethod.invokeExplosively (FrameworkMethod.java: 42) на org.junit.internal.runners.statements.InvokeMethod.evaluate (InvokeMethod.java:20) на org.junit.internal.runners.statements.RunBefores.evaluate (RunBefores.java:28) на org.junit.internal.runners.statements.RunAfters.evaluate (RunAfters.java:30) на org.junit.runners.ParentRunner.runLeaf (ParentRunner.java:263) при org.junit.runners.BlockJUnit4ClassRunner.runChild (BlockJUnit4ClassRunner.java:68)на org.junit.runners.BlockJUnit4ClassRunner.runChild (BlockJUnit4ClassRunner.java:47) в org.junit.runners.ParentRunner $ 3.run (ParentRunner.java:231) в org.junit.runners.ParentRunner $ 1.schedule (ParentRunner.java:60) в org.junit.runners.ParentRunner.runChildren (ParentRunner.java:229) в org.junit.runners.ParentRunner.access $ 000 (ParentRunner.java:50) в org.junit. runners.ParentRunner $ 2.оценить (ParentRunner.java:222) в org.junit.runners.ParentRunner.run (ParentRunner.java:300) в org.junit.runners.Suite.runChild (Suite.java:128) at org.junit.runners.Suite.runChild (Suite.java:24) в org.junit.runners.ParentRunner $ 3.run (ParentRunner.java:231) в org.junit.runners.ParentRunner $ 1.schedule (ParentRunner.java:60) при org.junit.runners.ParentRunner.runChildren (ParentRunner.java:229) на org.junit.runners.ParentRunner.access $ 000 (ParentRunner .java: 50) at org.junit.runners.ParentRunner $ 2.оценить (ParentRunner.java:222) в org.junit.runners.ParentRunner.run (ParentRunner.java:300) в org.junit.runner. JUnitCore.run (JUnitCore.java:157) при org.junit.runner.JUnitCore.run (JUnitCore.java:136) при android.support.test.runner.AndroidJUnitRunner.onStart (AndroidJUnitRunner.java:270) на android.app.Инструментация $ InstrumentationThread.run (Instrumentation.java:1551)
Я прочитал документы эспрессо и кинжала и искал проблемы в Github безрезультатно. Буду признателен за любую помощь, которую любой может предоставить. Заранее спасибо.
Редактировать # 1
Я последовал предложение Даниила о продлении испытательного бегуна и чекает VerifyError, и получил следующую трассировку стеки:
java.lang.ExceptionInInitializerError
at org.mockito.internal.creation.cglib.ClassImposterizer.createProxyClass(ClassImposterizer.java:95)
at org.mockito.internal.creation.cglib.ClassImposterizer.imposterise(ClassImposterizer.java:57)
at org.mockito.internal.creation.cglib.ClassImposterizer.imposterise(ClassImposterizer.java:49)
at org.mockito.internal.creation.cglib.CglibMockMaker.createMock(CglibMockMaker.java:24)
at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:33)
at org.mockito.internal.MockitoCore.mock(MockitoCore.java:59)
at org.mockito.Mockito.mock(Mockito.java:1285)
at org.mockito.Mockito.mock(Mockito.java:1163)
at com.mypackage.injection.EspressoRemoteResourcesModule.<init>(EspressoRemoteResourcesModule.java:17)
at com.mypackage.injection.MyCustomEspressoApplication.getEspressoRemoteResourcesModule(MyCustomEspressoApplication.java:52)
at com.mypackage.injection.MyCustomEspressoApplication.getModules(MyCustomEspressoApplication.java:24)
at com.mypackage.injection.MyCustomApplication.onCreate(MyCustomApplication.java:18)
at com.mypackage.injection.MyCustomEspressoApplication.onCreate(MyCustomEspressoApplication.java:16)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:999)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4151)
at android.app.ActivityThread.access$1300(ActivityThread.java:130)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1255)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.VerifyError: org/mockito/cglib/core/ReflectUtils
at org.mockito.cglib.core.KeyFactory$Generator.generateClass(KeyFactory.java:167)
at org.mockito.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
at org.mockito.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:217)
at org.mockito.cglib.core.KeyFactory$Generator.create(KeyFactory.java:145)
at org.mockito.cglib.core.KeyFactory.create(KeyFactory.java:117)
at org.mockito.cglib.core.KeyFactory.create(KeyFactory.java:109)
at org.mockito.cglib.core.KeyFactory.create(KeyFactory.java:105)
at org.mockito.cglib.proxy.Enhancer.<clinit>(Enhancer.java:70)
at org.mockito.internal.creation.cglib.ClassImposterizer.createProxyClass(ClassImposterizer.java:95)
at org.mockito.internal.creation.cglib.ClassImposterizer.imposterise(ClassImposterizer.java:57)
at org.mockito.internal.creation.cglib.ClassImposterizer.imposterise(ClassImposterizer.java:49)
at org.mockito.internal.creation.cglib.CglibMockMaker.createMock(CglibMockMaker.java:24)
at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:33)
at org.mockito.internal.MockitoCore.mock(MockitoCore.java:59)
at org.mockito.Mockito.mock(Mockito.java:1285)
at org.mockito.Mockito.mock(Mockito.java:1163)
at com.mypackage.injection.EspressoRemoteResourcesModule.<init>(EspressoRemoteResourcesModule.java:17)
at com.mypackage.injection.MyCustomEspressoApplication.getEspressoRemoteResourcesModule(MyCustomEspressoApplication.java:52)
at com.mypackage.injection.MyCustomEspressoApplication.getModules(MyCustomEspressoApplication.java:24)
at com.mypackage.injection.MyCustomApplication.onCreate(MyCustomApplication.java:18)
at com.mypackage.injection.MyCustomEspressoApplication.onCreate(MyCustomEspressoApplication.java:16)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:999)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4151)
at android.app.ActivityThread.access$1300(ActivityThread.java:130)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1255)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
04-29 06:40:28.594 1016-1016/? W/ActivityManager﹕ Error in app com.mypackage running instrumentation ComponentInfo{com.mypackage.test/com.mypackage.EspressoTestRunner}:
04-29 06:40:28.594 1016-1016/? W/ActivityManager﹕ java.lang.VerifyError
04-29 06:40:28.594 1016-1016/? W/ActivityManager﹕ java.lang.VerifyError: org/mockito/cglib/core/ReflectUtils
Это указало мне на Mockito. Мне не хватало необходимых библиотек mockito и dexmaker.
Я обновил свои зависимости для:
androidTestCompile 'org.mockito:mockito-core:1.10.19'
androidTestCompile 'com.google.dexmaker:dexmaker:1.2'
androidTestCompile ('com.google.dexmaker:dexmaker-mockito:1.2') {
exclude module: 'hamcrest-core'
exclude module: 'mockito-core'
}
androidTestCompile('com.android.support.test.espresso:espresso-core:2.0') {
exclude group: 'javax.inject'
}
I также отменяют MyCustomModule, которые необходимо включить EspressoRemoteResourcesModule. Как только я это сделал, это начало работать.
Пробовал это, теперь я получаю: Тесты на nexus_5_android_4_0_3 (AVD) - 4.1.1 не удалось: запуск инструментария завершился неудачно из-за «java.lang.VerifyError» : app: connectedAndroidTest FAILED com.android.builder.testing.ConnectedDevice> hasTests [nexus_5_android_4_0_3 (AVD) - 4.1 .1] [31mFAILED [0m Не найдено ни одного теста. Кажется, это новая земля. Есть ли другой метод, который мне нужно переопределить, чтобы он обнаружил тесты? – jameskbride
Можете ли вы вставить полный 'VerifyError' (должен быть в logcat, я думаю) и любые предупреждения' dalvikvm'? 'Не найденные тесты 'обычно означает, что во время установки бегуна произошла ошибка, прежде чем испытания начались. –
См. Мое редактирование выше. Версия TL; DR - это то, что вы указали мне в правильном направлении, расширив тестовый бегун и проверив VerifyError, который указал мне на Mockito и Dexmaker. Спасибо за помощь! – jameskbride