Android Architecture Component ViewModel - How to

2019-06-16 15:00发布

问题:

I'm trying to setup UI testing similar to GithubBrowserSample and it looks like the sample project only has mock ViewModel for Fragment but not an example for Activity.

Here's my code where I am trying to test the Activity by mocking ViewModel. But the ViewModel is not getting set before onCreate() in Activity.

@RunWith(AndroidJUnit4::class)
class MainActivityTest {

    val viewModel = mock(MainViewModel::class.java)

    @Rule
    @JvmField
    val activityRule = ActivityTestRule<MainActivity>(MainActivity::class.java, true, true)

    private val liveData = MutableLiveData<Resource<Object>>()

    @Before
    open fun setUp() {
        activityRule.activity.viewModelFactory = createViewModelFor(viewModel)
        `when`(viewModel.liveData).thenReturn(liveData)
        viewModel.liveData?.observeForever(mock(Observer::class.java) as Observer<Resource<Object>>)
        liveData.postValue(Resource.success(Object()))
    }

    fun <T : ViewModel> createViewModelFor(model: T): ViewModelProvider.Factory =
        object : ViewModelProvider.Factory {
            override fun <T : ViewModel> create(modelClass: Class<T>): T {
                if (modelClass.isAssignableFrom(model.javaClass)) {
                    return model as T
                }
                throw IllegalArgumentException("unexpected model class " + modelClass)
            }
        }
}

Can someone help me about this issue please?

回答1:

JUnit @Rules do their setup before @Before methods, so your activity is launching and starting its lifecycle before your setUp() method gets called. To avoid this, pass false as the third parameter to the rule constructor. This tells it not to launch the activity automatically, so you can do your setup in advance.

Then, you need to launch the activity manually before you run your tests. You can create an intent like val intent = Intent(InstrumentationRegistry.targetContext, MainActivity::class.java) and then pass it to activityRule.launchActivity(intent).