mardi 19 octobre 2021

JUnit test ViewModel in a MVVM Android App

I am developing an Android App following MVVM pattern to download data from an API. Data is returned as a Json array and displayed in a RecyclerView. I want to write a JUnit test for the ViewModel whose code is as follows. ItemResponse is a class containing a list of Json objects received by the API, each represented by an object of a class named Item (the model).

public class ItemViewModel extends AndroidViewModel {
    private LiveData<ItemResponse> itemsResponseLiveData;

    public ItemViewModel(@NonNull Application application) {
        super(application);
    }

    public void init() {
        ItemsRepository itemsRepository = new ItemsRepository();
        itemsResponseLiveData = itemsRepository.getItemsResponseLiveData();
    }

    public LiveData<ItemResponse> getItemsResponseLiveData() {
        return itemsResponseLiveData;
    }

    public void setItemsResponseLiveData(LiveData<ItemResponse> itemsResponseLiveData) {
    this.itemsResponseLiveData = itemsResponseLiveData;
    }
}

This is ItemResponse code:

public class ItemResponse {
    ArrayList<Item> items = null;

    public ItemResponse(ArrayList<Item> items) {
        setItems(items);
    }

    public ArrayList<Item> getItems() {
        return items;
    }

    public void setItems(ArrayList<Item> items) {
        this.items = items;
    }
}

The view is managed by a fragment that registers itself as an observer with the following code.

ItemViewModel viewModel = new ViewModelProvider(this).get(ItemViewModel.class);
viewModel.init();
viewModel.getItemsResponseLiveData().observe(this, new Observer<ItemResponse>() {
    @Override
    public void onChanged(ItemResponse itemResponse) {
        if (itemResponse != null) {
                // An adapter is updated
        }
    }
});

I would like to test the ViewHolder by instantiating it, registering an observer and providing some dummy data to check if the notification works by comparing the notified Item with the one added to LiveData. I wrote the following class, but when I run it, I get a NullPointerException at the viewModel = new ViewModelProvider line saying attempt to invoke virtual method 'androidx.lifecycle.ViewModel androidx.lifecycle.ViewModelStore.get(java.lang.String)' on a null object reference.

@RunWith(AndroidJUnit4.class)
public class ServiceAvailabilityTest extends TestCase implements ViewModelStoreOwner, LifecycleOwner {

    private ItemViewModel viewModel;

    @Before
    @Override
    public void setUp() throws Exception {
        super.setUp();

        viewModel = new ViewModelProvider(this).get(ItemViewModel.class);
        viewModel.init();

        viewModel.getItemsResponseLiveData().observe(this, new Observer<ItemResponse>() {
            @Override
            public void onChanged(ItemResponse itemResponse) {
                if (itemResponse != null) {
                    assertEquals(itemResponse.getItems().get(0).getName(), name);
                }
            }
        });
    }

    @Test
    public void testItemViewModel() {
        Item item = new Item("name", "description", "test1", "test1", "test3");
        ArrayList<Item> listItems = new ArrayList<>();
        listItems.add(item);
        ItemResponse itemResponse = new ItemResponse(listItems);

        MutableLiveData<ItemResponse> itemsResponseMutableLiveData = new MutableLiveData<>();
        itemsResponseMutableLiveData.postValue(itemResponse);

        viewModel.setItemsResponseLiveData(itemsResponseMutableLiveData);
    }

    @NonNull
    @Override
    public ViewModelStore getViewModelStore() {
        return null;
    }

    @NonNull
    @Override
    public Lifecycle getLifecycle() {
        return null;
    }
}

What is the correct way to test the ViewModel?

Aucun commentaire:

Enregistrer un commentaire