Использование Dagger 2 для внедрения зависимостей означает, что вы можете внедрить поддельные / фиктивные объекты для тестирования. Я использовал поддельный AndroidInjector, чтобы сделать это в своих тестах Espresso для старого приложения Android, которое я обновлял, но обнаружил, что при обновлении Dagger до более новой версии (с 2.14 до 2.21) пользовательский AndroidInjector больше не компилируется.
Поддельный AndroidInjector, который я использовал, был основан на этих блогах, которые были написаны пару лет назад:
- Тест эспрессо-активности с Android-инжектором Dagger
- Эспрессо-тестирование фрагментов с помощью инжектора Dagger для Android
- https://github.com/SabagRonen/dagger-activity-test-sample
Другая версия этой идеи может быть найдена здесь:
Это быстрый пост о том, как это можно исправить для тех, кто все еще использует код из этих статей (также запоздалое спасибо авторам за то, что они выдвинули эти идеи).
Это не компилируется …
Проблема возникла с этими внутренними изменениями в коде Dagger в версии 2.19.
https://github.com/google/dagger/releases/tag/dagger-2.19
Простые исправления
Основываясь на коде из статей, упомянутых выше, просто нужно внести некоторые простые изменения (к сожалению, я потратил некоторое время на разработку!).
1. Заменить устаревшую аннотацию
1
|
@ActivityKey |
с участием
1
|
@ClassKey |
2. Общая типизация для AndroidInjector.Factory и других классов, используемых в коде AndroidInjector, изменилась с
1
2
|
<? extends Activity> // java <out Activity> // kotlin |
в
1
2
|
<?> // java <*> // kotlin |
3. DispatchingAndroidInjector изменил свою подпись конструктора. Вместо того, чтобы иметь единственный параметр Map провайдера AndroidInjector.Factory с ключом по классу, теперь есть дополнительный параметр Map, использующий String (имя класса) в качестве ключа
Таким образом, в сгенерированном коде Dagger (и в поддельном AndroidInjector) метод DispatchingAndroidInjector_Factory.newDispatchingAndroidInjector () также нуждается в этом дополнительном параметре (даже если это просто пустая карта).
01
02
03
04
05
06
07
08
09
10
11
|
// java (pseudo-code) Map<Class<?>, Provider<AndroidInjector.Factory<?>>> classMap = new HashMap<>( 1 ); // create a custom AndroidInjector.Factory and add it to the provider Provider<AndroidInjector.Factory<?>> provider = ... map.put(MyActivity. class , provider); // empty map to satisfy method signature for newDispatchingAndroidInjector() Map<String, Provider<AndroidInjector.Factory<?>>> stringMap = new HashMap<>(); return DispatchingAndroidInjector_Factory.newDispatchingAndroidInjector(classMap, stringMap); |
1
2
3
4
5
6
7
8
9
|
// kotlin val classMap : Map<Class<*>, Provider<AndroidInjector.Factory<*>>> = mapOf( Pair<Class<*>, Provider<AndroidInjector.Factory<*>>>(T:: class .java, Provider { factory })) // empty map to satisfy method signature for newDispatchingAndroidInjector() val stringMap : Map<String, Provider<AndroidInjector.Factory<*>>> = emptyMap<String, Provider<AndroidInjector.Factory<*>>>() return DispatchingAndroidInjector_Factory.newDispatchingAndroidInjector<Activity>(classMap, stringMap) |
Зачем использовать поддельный AndroidInjector?
Более распространенный способ получения тестовых зависимостей Dagger заключается в том, чтобы поддерживать параллельный набор тестовых компонентов и тестовых модулей для обеспечения поддельных зависимостей. Это прекрасно работает и имеет преимущества, которые не должны ломаться из-за внутренних изменений в коде Dagger. Однако это также означает, что нужно поддерживать больше стандартного кода.
Опубликовано на Java Code Geeks с разрешения Дэвида Вонга, партнера нашей программы JCG . Смотрите оригинальную статью здесь: Обновите ваш поддельный AndroidInjector Мнения, высказанные участниками Java Code Geeks, являются их собственными. |