Search code examples
androidunit-testingandroid-fragmentsdagger-2android-architecture-components

How to create Android UI Test for Android App Architecture ViewModels?


I have been working with the new Android App Architecture Components. The documentation on testing leaves a lot to the imagination. I have looked at android architecture components testing part of the documentation it was very vague as worded below.

User Interface & Interactions: This will be the only time you need an Android UI Instrumentation test. The best way to test UI code is to create an Espresso test. You can create the fragment and provide it a mock ViewModel. Since the fragment only talks to the ViewModel, mocking it will be sufficient to fully test this UI

How do you go about writing a Espresso test by passing in a mock of a ViewModel to the fragment? I have also looked at the sample apps provided by Google they were also not very helpful.

Suppose this is my example fragment class.

public class ExampleFragment extends LifecycleFragment {
    private ExampleViewModel mViewModel;
    @Inject ExampleViewModelFactory mViewModelFactory;

    public ExampleFragment() {
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {        
        return inflater.inflate(R.layout.fragment_example, container, false);  
    }

    @Override
    public void onActivityCreated(@Nullable final Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    ExampleComponent component = DaggerExampleComponent.builder().build();
    component.inject(this);
    mViewModel = ViewModelProviders.of(this, mViewModelFactory).get(ExampleViewModel.class);
    mViewModel.getExampleString().observe(this, exampleString -> {
       //Update UI
        });        
    }
}  

Solution

  • There are two main approaches AFAIK about providing mock injected components. The first one is the one implemented in google examples, which is to provide a mock viewmodel implementation as a different flavour (for example in your tests).

    The other one is described in my blogpost here in the "testing the view" section, where the DaggerExampleComponent is provided by the Application object, and you override the application object in the espresso test runner having one that provides the fake ViewModel.

    Full working example here