Проблема с инъекцией кинжала в Fragment Test - PullRequest
0 голосов
/ 20 апреля 2020

Я основываю свою разработку приложений на GithubBrowserSample на основе примеров Android / Architecture-components-samples, включая тесты. Я уже провел свои локальные модульные тесты, но с тестом пользовательского интерфейса я столкнулся с некоторыми проблемами.

Когда я пытаюсь проверить любой фрагмент, я всегда получаю

java.lang.RuntimeException: kotlin.UninitializedPropertyAccessException: lateinit property viewModelFactory has not been initialized

Это мой фрагмент test

@RunWith(AndroidJUnit4::class)
class AccountListFragmentTest {

    @Rule
    @JvmField
    val executorRule = TaskExecutorWithIdlingResourceRule()

    @Rule
    @JvmField
    val countingAppExecutors = CountingAppExecutorsRule()

    @Rule
    @JvmField
    val dataBindingIdlingResourceRule = DataBindingIdlingResourceRule()

    private val navController = mock<NavController>()
    private val accountsLiveData = MutableLiveData<Resource<Accounts>>()
    private val triggerLiveData = MutableLiveData<Boolean>()
    private lateinit var viewModel: AccountListViewModel

    @Before
    fun init() {
        viewModel = mock(AccountListViewModel::class.java)

        `when`(viewModel.trigger).thenReturn(triggerLiveData)
        `when`(viewModel.accounts).thenReturn(accountsLiveData)
        doNothing().`when`(viewModel).setTrigger(true)

        val scenario = launchFragmentInContainer {
            AccountListFragment().apply {
                appExecutors = countingAppExecutors.appExecutors
                viewModelFactory = ViewModelUtil.createFor(viewModel)
            }
        }

        dataBindingIdlingResourceRule.monitorFragment(scenario)

        scenario.onFragment { fragment ->
            Navigation.setViewNavController(fragment.requireView(), navController)
            fragment.disableProgressBarAnimations()
        }
    }

    ...

}

И в своем фрагменте я внедряю такие зависимости как этот

class AccountListFragment: Fragment(), Injectable {
    @Inject
    lateinit var viewModelFactory: ViewModelProvider.Factory
    @Inject
    lateinit var appExecutors: AppExecutors

    ...

Так что я подумал, что это будет связано с внедрением зависимостей. В GithubBrowserSample они упоминают, что вам нужно создать TestApp и CustomTestRunner, чтобы избежать внедрения зависимостей Dagger. Я уже сделал это и добавил его в build.gradle

class TestApp : Application()

class CustomTestRunner : AndroidJUnitRunner() {
    override fun newApplication(cl: ClassLoader, className: String, context: Context): Application {
        return super.newApplication(cl, TestApp::class.java.name, context)
    }
}

//build.gradle
defaultConfig {
    ...
    testInstrumentationRunner "com.example.app.util.CustomTestRunner"
}

Мой viewModel уже имеет @ Аннотация OpenForTesting, я использую другую viewModelFactory для предоставления моих viewModels, поэтому я не знаю, что еще мне нужно сделать, чтобы это заработало.

Я запускаю свои тесты с эмулятором Android Pixel 2 Api 29.

Я ценю всю вашу помощь.

...