Android LiveData测试:如何校验Category列表是否为空?能否用Mockito?
Great question! Let's break down how to test that your LiveData<List<Category>> returns a non-empty list, and whether Mockito is useful here.
First, let's cover how to properly test your existing MockCategoriesRepository to verify the returned list isn't empty. Then we'll address the Mockito question.
Testing Your Current Mock Repository
When working with LiveData in unit tests, you need to ensure the LiveData has an active observer to guarantee the value is delivered (even if it's set synchronously like in your mock). Here's how to adjust your test:
Option 1: Without Mockito (Using a Custom Observer)
If you don't want to bring in Mockito just for this test, you can capture the LiveData value with a simple custom observer:
@Test public void getAllCategories_returnsNonEmptyList() { // Set up your mock repository CategoriesRepository categoriesRepository = new MockCategoriesRepository(); LiveData<List<Category>> allCategories = categoriesRepository.getAllCategories(); // Create a way to capture the emitted list final List<Category>[] capturedCategories = new List[1]; Observer<List<Category>> testObserver = categories -> capturedCategories[0] = categories; // Start observing the LiveData (observeForever works for unit tests since there's no lifecycle) allCategories.observeForever(testObserver); // Now assert the captured list is valid assertNotNull("Categories list should not be null", capturedCategories[0]); assertFalse("Categories list should not be empty", capturedCategories[0].isEmpty()); assertEquals("Categories list should have 3 items", 3, capturedCategories[0].size()); // Clean up: remove the observer to avoid test leaks allCategories.removeObserver(testObserver); }
Option 2: With Mockito (Using a Mock Observer)
If you already use Mockito in your test suite, you can use it to verify the observer was called and then check the value:
@Test public void getAllCategories_returnsNonEmptyList_withMockito() { CategoriesRepository categoriesRepository = new MockCategoriesRepository(); LiveData<List<Category>> allCategories = categoriesRepository.getAllCategories(); // Create a mock Observer with Mockito Observer<List<Category>> mockObserver = Mockito.mock(Observer.class); allCategories.observeForever(mockObserver); // Verify the observer received an update Mockito.verify(mockObserver).onChanged(Mockito.anyList()); // Get the value directly from LiveData and assert List<Category> categories = allCategories.getValue(); assertNotNull(categories); assertFalse(categories.isEmpty()); allCategories.removeObserver(mockObserver); }
Do You Need Mockito for This?
In your current setup, you don't strictly need Mockito—your handwritten MockCategoriesRepository works perfectly fine for this test. However, Mockito can simplify things if you want to avoid maintaining a separate mock class.
For example, instead of writing MockCategoriesRepository, you could mock the CategoriesRepository interface directly with Mockito:
@Test public void getAllCategories_returnsNonEmptyList_withMockitoMockedRepo() { // Mock the repository interface CategoriesRepository mockRepo = Mockito.mock(CategoriesRepository.class); // Create your test data List<Category> testCategories = Arrays.asList(new Category(), new Category(), new Category()); MutableLiveData<List<Category>> mockLiveData = new MutableLiveData<>(testCategories); // Stub the repository method to return our test LiveData Mockito.when(mockRepo.getAllCategories()).thenReturn(mockLiveData); // Get the result from the mocked repo LiveData<List<Category>> result = mockRepo.getAllCategories(); // Assert the result is valid (using the same observer approach as before) final List<Category>[] captured = new List[1]; result.observeForever(categories -> captured[0] = categories); assertNotNull(captured[0]); assertFalse(captured[0].isEmpty()); result.removeObserver(categories -> captured[0] = categories); }
This way, you don't have to write and maintain a full mock class—Mockito handles stubbing the method's return value for you.
Key Takeaways
- LiveData Requires Observation: Always observe LiveData in tests to ensure the value is delivered.
observeForeveris ideal for unit tests since there's no Android lifecycle involved. - Assertions: Use standard JUnit assertions (or AssertJ for more readable messages) to validate the list's state.
- Mockito's Role: Mockito is optional here, but it's a great tool to reduce boilerplate when mocking interfaces instead of writing concrete mock classes.
内容的提问来源于stack exchange,提问作者ip696

