Модульное тестирование фрагментов, использующих lateinit ViewModel - PullRequest
0 голосов
/ 14 ноября 2018

Я пытаюсь написать некоторые модульные тесты для проекта Android, но изо всех сил пытаюсь найти решение, которое соответствует установленной архитектуре.

Просто для справки, вот пример архитектуры, установленной для входа в систему:

LoginFragment

class LoginFragment : Fragment(), Injectable {

    /**
     * VARIABLES
     */

    @Inject
    lateinit var viewModelFactory: ViewModelProvider.Factory
    lateinit var loginViewModel: LoginViewModel

    var binding by autoCleared<LoginFragmentBinding>()
    var dataBindingComponent: DataBindingComponent = FragmentDataBindingComponent(this)

    // Fragment life cycle and other methods

}

LoginViewModel

class LoginViewModel
@Inject constructor(val authRepository: AuthRepository) : ViewModel() {

   fun login(username: String, password: String): LiveData<LoginResponse> { 

    authRepository.login(username, password)


}

LoginRepository

@Singleton
class AuthRepository @Inject constructor(
    val projectService: ProjectService,
    val sessionData: SharedPrefs
) {

     fun login(username: String, password: String): LiveData<LoginResponse> {

         // Login logic

     }
}

Служба проекта

interface ProjectService {

    @POST("user/login")
    fun postLogin(@Body body: LoginBody): LiveData<ApiResponseWrapper<LoginRemote>>

}

После этого я считаю, что мне нужно инициализировать экземпляр LoginFragment , чтобы получить доступ к ViewModel и выполнить вход в систему. Я думаю, что это необходимо, потому что фрагмент связывает все для совместной работы (не уверен, это не моя установка, и я новичок в разработке Android).

Есть ли лучший способ получить доступ к функции входа ViewModel, чтобы запускать модульные тесты для его вызовов с установленной архитектурой?

Далее, в качестве примера, вот пример того, как я пытаюсь проверить вход пользователя в систему:

LoginViewModelTests

@Test
fun login() {

    //
    val result = runBlocking {
        loginCoroutine()
    }

    Assert.assertTrue(result)
}

suspend fun loginCoroutine(): Boolean {

    val loginFragment = LoginFragment()

    return suspendCoroutine { continuation ->
        loginFragment.loginViewModel
                .login(maleUsername, malePassword)
                .observe(loginFragment, Observer {
                    loginFragment.activity?.onResult(it?.result,

                            onSuccess = {
                                continuation.resume(true)
                            },
                            onValidationError = {
                                continuation.resume(false)
                            })
                })
    }

}

Как видите, я инициализирую LoginFragment , чтобы вызвать loginViewModel login . И затем после завершения я могу запустить свои тесты для ответа.

Однако при попытке запуска выдается ошибка:

lateinit property loginViewModel has not been initialized

Как мне решить эту проблему, если она является инъецируемой переменной lateinit? Или что рекомендуется проверить этот метод входа в систему на реализацию, которую я пытаюсь?

...