Недавно я перешел с кинжалом, потому что концепция DI имеет смысл. Один из лучших "побочных продуктов" DI (как Джейк Уортон, поставленный в одной из его презентаций) легче тестировать.
Итак, теперь я в основном использую эспрессо для выполнения некоторых функциональных тестов, и я хочу иметь возможность вводить фиктивные/макетные данные в приложение и показывать их активность. Я предполагаю, что это одно из самых больших преимуществ DI, это должно быть относительно просто спросить. Однако по какой-то причине я не могу обернуть вокруг себя голову. Любая помощь приветствуется. Вот что я до сих пор (я написал пример, который отражает мою текущую настройку):
public class MyActivity
extends MyBaseActivity {
@Inject Navigator _navigator;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyApplication.get(this).inject(this);
// ...
setupViews();
}
private void setupViews() {
myTextView.setText(getMyLabel());
}
public String getMyLabel() {
return _navigator.getSpecialText(); // "Special Text"
}
}
Это мои модули кинжалов:
// Navigation Module
@Module(library = true)
public class NavigationModule {
private Navigator _nav;
@Provides
@Singleton
Navigator provideANavigator() {
if (_nav == null) {
_nav = new Navigator();
}
return _nav;
}
}
// App level module
@Module(
includes = { SessionModule.class, NavigationModule.class },
injects = { MyApplication.class,
MyActivity.class,
// ...
})
public class App {
private final Context _appContext;
AppModule(Context appContext) {
_appContext = appContext;
}
// ...
}
В моем тесте эспрессо я пытаюсь вставить макет модуля следующим образом:
public class MyActivityTest
extends ActivityInstrumentationTestCase2<MyActivity> {
public MyActivityTest() {
super(MyActivity.class);
}
@Override
public void setUp() throws Exception {
super.setUp();
ObjectGraph og = ((MyApplication) getActivity().getApplication()).getObjectGraph().plus(new TestNavigationModule());
og.inject(getActivity());
}
public void test_SeeSpecialText() {
onView(withId(R.id.my_text_view)).check(matches(withText(
"Special Dummy Text)));
}
@Module(includes = NavigationModule.class,
injects = { MyActivityTest.class, MyActivity.class },
overrides = true,
library = true)
static class TestNavigationModule {
@Provides
@Singleton
Navigator provideANavigator() {
return new DummyNavigator(); // that returns "Special Dummy Text"
}
}
}
Это не работает вообще. Мои тесты эспрессо выполняются, но TestNavigationModule полностью игнорируется... arr...: (
Что я делаю неправильно? Есть ли лучший подход к издевательствам модулей с Espresso. Я искал и видел примеры использования Robolectric, Mockito и т.д. Но я просто хочу чистые тесты эспрессо и мне нужно поменять модуль на мой макет. Как я должен это делать?
EDIT:
Итак, я пошел с подходом @user3399328 к определению определения статического тестового модуля, проверяя значение null и затем добавляя его в свой класс Application. Тем не менее, я все еще не получаю свою тестовую версию класса. У меня есть чувство, хотя, вероятно, что-то не так с определением модуля тестирования кинжала, а не с моим жизненным циклом эспрессо. Причина, по которой я делаю предположение, заключается в том, что я добавляю операторы отладки и обнаруживаю, что статический тестовый модуль не является пустым во время инъекции в классе приложения. Не могли бы вы указать мне направление того, что я могу сделать неправильно. Вот фрагменты кода моих определений:
MyApplication:
@Override
public void onCreate() {
// ...
mObjectGraph = ObjectGraph.create(Modules.list(this));
// ...
}
Модули:
public class Modules {
public static List<Object> _testModules = null;
public static Object[] list(MyApplication app) {
// return new Object[]{ new AppModule(app) };
List<Object> modules = new ArrayList<Object>();
modules.add(new AppModule(app));
if (_testModules == null) {
Log.d("No test modules");
} else {
Log.d("Test modules found");
}
if (_testModules != null) {
modules.addAll(_testModules);
}
return modules.toArray();
}
}
Модифицированный тестовый модуль в моем классе:
@Module(overrides = true, library = true)
public static class TestNavigationModule {
@Provides
@Singleton
Navigator provideANavigator()() {
Navigator navigator = new Navigator();
navigator.setSpecialText("Dummy Text");
return navigator;
}
}