Back to Repositories

Testing FileDescriptor Local URI Fetching in Glide

This test suite validates the FileDescriptorLocalUriFetcher class functionality in Glide, focusing on local URI resource loading and file descriptor handling. It ensures proper handling of file descriptors and error cases when fetching resources from local URIs.

Test Coverage Overview

The test suite provides comprehensive coverage of the FileDescriptorLocalUriFetcher component, focusing on two critical scenarios:
  • Successful file descriptor retrieval from local URIs
  • Error handling when file descriptors are null
Key integration points include the ContentResolver and Uri handling systems, with particular attention to resource loading outcomes.

Implementation Analysis

The testing approach utilizes Robolectric for Android environment simulation and Mockito for dependency mocking. The implementation follows a clear pattern of setting up test contexts, mocking file descriptors, and verifying callback behaviors.

The tests leverage RobolectricTestRunner and custom shadows for ContentResolver simulation, demonstrating sophisticated Android testing techniques.

Technical Details

Testing tools and configuration:
  • JUnit for test framework
  • Robolectric for Android runtime simulation
  • Mockito for mocking and verification
  • Custom ContentResolverShadow for file system operations
  • ApplicationProvider for context access

Best Practices Demonstrated

The test suite exemplifies several testing best practices:
  • Proper test isolation using @Before setup
  • Clear test method naming that describes functionality
  • Effective use of mocking to control dependencies
  • Comprehensive error case handling
  • Clean separation of test scenarios

bumptech/glide

library/test/src/test/java/com/bumptech/glide/load/data/resource/FileDescriptorLocalUriFetcherTest.java

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

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

import android.content.ContentResolver;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import androidx.test.core.app.ApplicationProvider;
import com.bumptech.glide.Priority;
import com.bumptech.glide.load.data.DataFetcher;
import com.bumptech.glide.load.data.FileDescriptorLocalUriFetcher;
import com.bumptech.glide.tests.ContentResolverShadow;
import java.io.FileNotFoundException;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;

@RunWith(RobolectricTestRunner.class)
@Config(
    sdk = ROBOLECTRIC_SDK,
    shadows = {ContentResolverShadow.class})
public class FileDescriptorLocalUriFetcherTest {

  @Mock private DataFetcher.DataCallback<ParcelFileDescriptor> callback;

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

  @Test
  public void testLoadResource_returnsFileDescriptor() throws Exception {
    Context context = ApplicationProvider.getApplicationContext();
    Uri uri = Uri.parse("file://nothing");

    ContentResolver contentResolver = context.getContentResolver();
    ContentResolverShadow shadow = Shadow.extract(contentResolver);

    AssetFileDescriptor assetFileDescriptor = mock(AssetFileDescriptor.class);
    ParcelFileDescriptor parcelFileDescriptor = mock(ParcelFileDescriptor.class);
    when(assetFileDescriptor.getParcelFileDescriptor()).thenReturn(parcelFileDescriptor);
    shadow.registerFileDescriptor(uri, assetFileDescriptor);

    FileDescriptorLocalUriFetcher fetcher =
        new FileDescriptorLocalUriFetcher(context.getContentResolver(), uri);
    fetcher.loadData(Priority.NORMAL, callback);
    verify(callback).onDataReady(eq(parcelFileDescriptor));
  }

  @Test
  public void testLoadResource_withNullFileDescriptor_callsLoadFailed() {
    Context context = ApplicationProvider.getApplicationContext();
    Uri uri = Uri.parse("file://nothing");

    ContentResolver contentResolver = context.getContentResolver();
    ContentResolverShadow shadow = Shadow.extract(contentResolver);
    shadow.registerFileDescriptor(uri, null /*fileDescriptor*/);

    FileDescriptorLocalUriFetcher fetcher =
        new FileDescriptorLocalUriFetcher(context.getContentResolver(), uri);
    fetcher.loadData(Priority.NORMAL, callback);
    verify(callback).onLoadFailed(isA(FileNotFoundException.class));
  }
}