Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Architecture Component ViewModel - How to mock ViewModel on test Activity?

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?

like image 208
Nux Avatar asked Dec 27 '17 08:12

Nux


1 Answers

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).

like image 176
RussHWolf Avatar answered Oct 19 '22 00:10

RussHWolf