Внедрить поставщика ViewModelProvider.Factory в тест esspresso

У меня есть собственная реализация ViewModel.Factory, которая предоставляется лямбдой, введенной Dagger2

interface ViewModelFactoryComponent {
    val factoryProvider: (Bundle?) -> ViewModelProvider.Factory
}

Реализация кинжала выглядит следующим образом:

@Module
class ViewModelModule {
    @Provides
    @Singleton
    fun bindViewModelFactory(creators: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<(Bundle?) -> ViewModel>>): (Bundle?) -> ViewModelProvider.Factory {
        return { ViewModelFactory(creators, it) }
    }
}

@Singleton
@Component(modules = [ ApplicationModule::class, ViewModelModule::class])
interface ApplicationComponent : ViewModelFactoryComponent

В приложении все работает как часы, но проблема возникла, когда я попытался настроить Espresso тест. Вот конфигурация компонента Dagger Test:

@Singleton
@Component(modules = [ApplicationModule::class, ViewModelModule::class])
interface TestComponent : ApplicationComponent

Теперь в чем проблема - реализация тестового компонента, сгенерированная функцией генерации кинжала, подобной этой

 @Override
  public Function1<Bundle, ViewModelProvider$Factory> getFactoryProvider() {
    return bindViewModelFactoryProvider.get();
  }

которые генерируют ошибку компиляции, как в реальном приложении:

  @Override
  public Function1<Bundle, ViewModelProvider.Factory> getFactoryProvider() {
    return bindViewModelFactoryProvider.get();
  }

Сначала я подумал, что дело в видимости ViewModelProvider.Factory, но все модификации build.gradle не помогли. Я столкнулся с полным отсутствием идей, поэтому буду благодарен хотя бы за некоторые предложения.

ОБНОВЛЕНИЕ Я создал пустой проект, чтобы воспроизвести эту ошибку, и я полагаю, что она полностью повторяема.

Файл в каталоге main:


@Singleton
@Component(modules = [ViewModelModule::class])
interface ApplicationComponent : ViewModelFactoryComponent

@Module
class ViewModelModule {

    @Provides
    @Singleton
    fun bindViewModelFactory(): () -> ViewModelProvider.Factory {
        return { ViewModelFactory() }
    }
}

interface ViewModelFactoryComponent {
    val factoryProvider: () -> ViewModelProvider.Factory
}

class ViewModelFactory @Inject constructor() : ViewModelProvider.Factory {
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        return modelClass.newInstance()
    }
}

class MainActivity : AppCompatActivity()

Файл в каталоге androidTest:

@Singleton
@Component(modules = [ViewModelModule::class])
interface TestComponent : ApplicationComponent

@RunWith(AndroidJUnit4::class)
class TestCase {
    @get:Rule
    val activityTestRule = ActivityTestRule(MainActivity::class.java, false, false)

    @Test
    fun appLaunchesSuccessfully() {
        ActivityScenario.launch(MainActivity::class.java)
    }
}

И это все зависимости:

    implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'androidx.appcompat:appcompat:1.0.2'
    implementation 'com.google.dagger:dagger:2.21'
    kapt 'com.google.dagger:dagger-compiler:2.21'
    kaptAndroidTest 'com.google.dagger:dagger-compiler:2.21'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
    androidTestImplementation 'androidx.test.ext:junit:1.1.0'
    androidTestImplementation 'androidx.test:rules:1.1.1'

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

Редактировать Итак, я понял, что без kaptAndroidTest 'com.google.dagger:dagger-compiler:2.21' тестового проекта можно построить успешную сборку.
Плохая новинка в том, что без него класс компонента dagger не сгенерируется.


person Karol Kulbaka    schedule 27.03.2019    source источник
comment
трудно сказать наверняка, потому что эта ошибка компиляции была опущена.   -  person Martin Zeitler    schedule 27.03.2019
comment
@MartinZeitler Я добавлю трассировку стека, но там ничего интересного нет. Только что сгенерированная функция public Function1<Bundle, ViewModelProvider$Factory> getFactoryProvider() не компилируется из-за '$'   -  person Karol Kulbaka    schedule 28.03.2019


Ответы (2)


Думаю, вам нужен этот плагин:

apply plugin: 'kotlin-kapt'

с этими dependencies:

kapt "com.google.dagger:dagger-compiler:2.21"
implementation "com.google.dagger:dagger:2.21"

и включите опцию generateStubs:

kapt {
    generateStubs = true
}

есть много похожих вопросов ... также см. руководство пользователя.

kaptAndroidTest может быть бесполезным.

person Martin Zeitler    schedule 27.03.2019
comment
about generateStubs = true stackoverflow.com/questions/47044955/ - person Karol Kulbaka; 28.03.2019

Согласно https://github.com/google/dagger/issues/1454 и https://youtrack.jetbrains.net/issue/KT-27936 есть только временное решение по первой ссылке

person Karol Kulbaka    schedule 21.04.2019