在 init 块中使用 postValue 时出现 LiveData 单元测试错误 [英] LiveData unit testing error when using postValue in init block

查看:38
本文介绍了在 init 块中使用 postValue 时出现 LiveData 单元测试错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用实时数据为视图模型编写单元测试.

I'm trying to write a unit test for a view model using live data.

登录ViewModel.kt

class LoginViewModel @Inject constructor(
    val context: Context
): ViewModel() {
    val username = MutableLiveData<String>()
    val password = MutableLiveData<String>()
    val isLoginButtonEnabled = MediatorLiveData<Boolean>().apply {
        fun combineLatest(): Boolean {
            return !(username.value.isNullOrEmpty() || password.value.isNullOrEmpty())
        }
        addSource(username) { this.value = combineLatest() }
        addSource(password) { this.value = combineLatest() }
    }

    init {
        username.postValue("test")
        password.postValue("test")
    }
}

登录ViewModelTest.kt

@RunWith(MockitoJUnitRunner::class)
class LoginViewModelTest {
    @Rule
    @JvmField
    val instantTaskExecutorRole = InstantTaskExecutorRule()

    private val context = mock(Context::class.java)
    private val loginViewModel = LoginViewModel(context)

    @Test
    fun loginButtonDisabledOnEmptyUsername() {
        val observer = mock<Observer<Boolean>>()
        loginViewModel.isLoginButtonEnabled.observeForever(observer)
        loginViewModel.username.postValue("")

        verify(observer).onChanged(false)
    }
}

我的单元测试在 username.postValue("test") 行抛出以下异常:

My unit test throws the following exception at the line username.postValue("test"):

java.lang.RuntimeException: Method getMainLooper in android.os.Looper not mocked. See http://g.co/androidstudio/not-mocked for details.

InstantTaskExecutorRule 应该在使用实时数据时提供执行上下文,但是在 init 块中初始化实时数据时它不起作用.当省略 init 块时,它可以按需要工作,但我需要初始化实时数据变量的可能性.

The InstantTaskExecutorRule should provide an execution context when using live data, however it doesn't work when initializing live data in the init-block. When omitting the init-block it works as desired, but i need the possibility to initialize live data variables.

在单元测试视图模型时,有什么方法可以使实时数据初始化工作吗?

Is there any way to make the live data initialization work when unit testing view models?

推荐答案

我设法使用提到的规则对使用 LiveDataViewModel 进行单元测试 - InstantTaskExecutorRule.但就我而言,规则 val 声明有点不同:

I managed to unit test my ViewModel that was using LiveData using mentioned rula - InstantTaskExecutorRule. But in my case the rule val declaration was a bit different:

@Suppress("unused")
@get:Rule
val instantTaskExecutorRule: InstantTaskExecutorRule = InstantTaskExecutorRule()

@Before
@Throws(Exception::class)
fun prepare() {
    MockitoAnnotations.initMocks(this)
}

编辑 2:

出于某种奇怪的原因,我无法重现这个:)另外,我认为问题可能是因为您初始化 ViewModel 的方式 -

For some weird reason I cannot reproduce this :) Also, I think that the problem could be because of the way you're initializing your ViewModel -

private val loginViewModel = LoginViewModel(context)

我认为它初始化得太早,因此它的 init 块也太早被调用了.也许在 @Before 方法中创建它是合理的?喜欢:

I assume that it initializes too early, thus it's init block gets called too early too. Maybe it's reasonable to create it in the @Before method ? Like:

private lateinit var viewModel: LoginViewModel

@Before
@Throws(Exception::class)
fun prepare() {
    loginViewModel = LoginViewModel(context)
}

这篇关于在 init 块中使用 postValue 时出现 LiveData 单元测试错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆