Back to Repositories

Testing MediaStore Thumbnail Fetching Operations in Glide

This test suite validates the ThumbFetcher class functionality in Glide’s MediaStore integration, focusing on thumbnail loading and resource management. The tests verify proper handling of input streams, cleanup operations, and error scenarios when fetching media thumbnails.

Test Coverage Overview

The test suite provides comprehensive coverage of the ThumbFetcher component’s core operations.

Key areas tested include:
  • Successful thumbnail stream retrieval and callback handling
  • Proper resource cleanup and stream closing
  • Error handling for null input streams
  • Integration with MediaStore content URIs

Implementation Analysis

The testing approach utilizes Mockito for dependency isolation and behavior verification. The implementation leverages Robolectric for Android framework simulation, enabling MediaStore-related testing without a physical device.

Key patterns include:
  • Mock injection for ThumbnailStreamOpener and callback interfaces
  • URI path construction for MediaStore content
  • Priority-based data loading verification

Technical Details

Testing tools and configuration:
  • JUnit 4 test framework
  • Mockito for mocking and verification
  • Robolectric TestRunner with SDK configuration
  • MockitoAnnotations for automatic mock initialization
  • MediaStore URI manipulation utilities

Best Practices Demonstrated

The test suite exemplifies several testing best practices in Android development.

Notable practices include:
  • Proper test setup and tear down with @Before annotations
  • Isolated test cases with specific assertions
  • Resource cleanup verification
  • Null case handling
  • Mock behavior configuration for deterministic testing

bumptech/glide

library/test/src/test/java/com/bumptech/glide/load/data/mediastore/ThumbFetcherTest.java

            
package com.bumptech.glide.load.data.mediastore;

import static com.bumptech.glide.RobolectricConstants.ROBOLECTRIC_SDK;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.net.Uri;
import android.provider.MediaStore;
import com.bumptech.glide.Priority;
import com.bumptech.glide.load.data.DataFetcher;
import java.io.InputStream;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentMatchers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;

@RunWith(RobolectricTestRunner.class)
@Config(sdk = ROBOLECTRIC_SDK)
public class ThumbFetcherTest {

  @Mock private ThumbnailStreamOpener opener;
  @Mock private DataFetcher.DataCallback<InputStream> callback;
  @Mock private InputStream expected;

  private ThumbFetcher fetcher;
  private Uri uri;

  @Before
  public void setUp() {
    MockitoAnnotations.initMocks(this);

    uri = Uri.withAppendedPath(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, "123");
    fetcher = new ThumbFetcher(uri, opener);
  }

  @Test
  public void testReturnsInputStreamFromThumbnailOpener() throws Exception {
    when(opener.open(eq(uri))).thenReturn(expected);

    fetcher.loadData(Priority.LOW, callback);
    verify(callback).onDataReady(ArgumentMatchers.<InputStream>isNotNull());
  }

  @Test
  public void testClosesInputStreamFromThumbnailOpenerOnCleanup() throws Exception {
    when(opener.open(eq(uri))).thenReturn(expected);

    fetcher.loadData(Priority.HIGH, callback);

    fetcher.cleanup();
    verify(expected).close();
  }

  @Test
  public void testDoesNotThrowIfCleanupWithNullInputStream() {
    fetcher.cleanup();
  }
}