Статьи

Обновите ваш поддельный AndroidInjector

Использование Dagger 2 для внедрения зависимостей означает, что вы можете внедрить поддельные / фиктивные объекты для тестирования. Я использовал поддельный AndroidInjector, чтобы сделать это в своих тестах Espresso для старого приложения Android, которое я обновлял, но обнаружил, что при обновлении Dagger до более новой версии (с 2.14 до 2.21) пользовательский AndroidInjector больше не компилируется.

Поддельный AndroidInjector, который я использовал, был основан на этих блогах, которые были написаны пару лет назад:

Другая версия этой идеи может быть найдена здесь:

Это быстрый пост о том, как это можно исправить для тех, кто все еще использует код из этих статей (также запоздалое спасибо авторам за то, что они выдвинули эти идеи).

Это не компилируется …

Проблема возникла с этими внутренними изменениями в коде 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, являются их собственными.