Back to Repositories

Testing FileDescriptor Asset Path Fetching Implementation in Glide

This test suite validates the FileDescriptorAssetPathFetcher class in Glide, focusing on asset file descriptor handling and resource management. It ensures proper interaction with Android’s AssetManager and verifies cleanup behaviors for system resources.

Test Coverage Overview

The test suite provides comprehensive coverage of the FileDescriptorAssetPathFetcher functionality, including asset loading and resource management. Key areas tested include:

  • Asset file descriptor opening through AssetManager
  • Proper callback handling for loaded data
  • Resource cleanup operations
  • Cancellation behavior

Implementation Analysis

The testing approach utilizes Robolectric for Android environment simulation and Mockito for dependency mocking. The implementation follows a clear setup-execute-verify pattern, with each test focusing on a specific aspect of the fetcher’s lifecycle.

Tests are structured using JUnit annotations and leverage mock objects to isolate the system under test.

Technical Details

Testing tools and configuration:

  • JUnit for test framework
  • Robolectric for Android runtime simulation
  • Mockito for mocking dependencies
  • Custom SDK configuration for Robolectric
  • AssetManager and AssetFileDescriptor mocking

Best Practices Demonstrated

The test suite exemplifies several testing best practices:

  • Proper test isolation using @Before setup
  • Clear test method naming conventions
  • Efficient resource management testing
  • Comprehensive error case coverage
  • Mock verification for interaction testing

bumptech/glide

library/test/src/test/java/com/bumptech/glide/load/data/FileDescriptorAssetPathFetcherTest.java

            
package com.bumptech.glide.load.data;

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

import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import com.bumptech.glide.Priority;
import java.io.IOException;
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;

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

  @Mock private AssetManager assetManager;
  @Mock private AssetFileDescriptor assetFileDescriptor;
  @Mock private DataFetcher.DataCallback<AssetFileDescriptor> callback;

  private FileDescriptorAssetPathFetcher fetcher;

  @Before
  public void setUp() throws IOException {
    MockitoAnnotations.initMocks(this);
    String assetPath = "/some/asset/path";
    fetcher = new FileDescriptorAssetPathFetcher(assetManager, assetPath);
    when(assetManager.openFd(eq(assetPath))).thenReturn(assetFileDescriptor);
  }

  @Test
  public void testOpensInputStreamForPathWithAssetManager() throws Exception {
    fetcher.loadData(Priority.NORMAL, callback);
    verify(callback).onDataReady(eq(assetFileDescriptor));
  }

  @Test
  public void testClosesOpenedInputStreamOnCleanup() throws Exception {
    fetcher.loadData(Priority.NORMAL, callback);
    fetcher.cleanup();

    verify(assetFileDescriptor).close();
  }

  @Test
  public void testDoesNothingOnCleanupIfNoDataLoaded() throws IOException {
    fetcher.cleanup();
    verify(assetFileDescriptor, never()).close();
  }

  @Test
  public void testDoesNothingOnCancel() throws Exception {
    fetcher.loadData(Priority.NORMAL, callback);
    fetcher.cancel();
    verify(assetFileDescriptor, never()).close();
  }
}