【问题标题】:Inject provider of ViewModelProvider.Factory into esspresso test将 ViewModelProvider.Factory 的提供者注入 esspresso 测试
【发布时间】:2019-03-27 14:45:56
【问题描述】:

我有 ViewModel.Factory 的自定义实现,它由 Dagger2 注入的 lambda 提供

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

Dagger 实现如下所示:

@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 测试时出现了问题。这里是匕首测试组件配置:

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

现在有什么问题 - 像这样由 dagger generate 函数生成的测试组件实现

 @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'测试项目可以成功构建。
坏消息是没有它匕首组件类将不会生成。

【问题讨论】:

  • 很难确定,因为“编译错误”被省略了。
  • @MartinZeitler 我将添加堆栈跟踪,但那里没有任何兴趣。刚刚生成的函数public Function1&lt;Bundle, ViewModelProvider$Factory&gt; getFactoryProvider() 因为'$'而无法编译

标签: android kotlin dagger-2 android-espresso android-viewmodel


【解决方案1】:

认为你需要这个插件:

apply plugin: 'kotlin-kapt'

这些dependencies:

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

并启用选项generateStubs

kapt {
    generateStubs = true
}

有很多similar questions ...另请参阅user's guide

kaptAndroidTest 可能没用。

【讨论】:

【解决方案2】:

根据https://github.com/google/dagger/issues/1454https://youtrack.jetbrains.net/issue/KT-27936在第一个链接下只有一个临时解决方案

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-19
    • 2015-11-11
    • 2016-02-18
    • 1970-01-01
    • 2023-04-04
    • 1970-01-01
    • 2022-10-05
    • 2011-07-13
    相关资源
    最近更新 更多