Back to Repositories

Testing Dual-Layer Cache Implementation in androidutilcode

This test suite validates the CacheDoubleUtils class functionality in the androidutilcode library, which implements a dual-layer caching mechanism using both memory and disk storage. The suite thoroughly tests cache operations for various data types including bytes, strings, JSON, bitmaps, and custom objects.

Test Coverage Overview

The test suite provides comprehensive coverage of CacheDoubleUtils functionality:
  • Cache operations for multiple data types (bytes, strings, JSON, bitmaps)
  • Memory and disk cache synchronization
  • Cache size and count verification
  • Edge cases for cache removal and clearing
  • Custom object caching with Parcelable and Serializable implementations

Implementation Analysis

The testing approach employs JUnit 4 framework with systematic verification of cache operations:
  • Setup and teardown patterns for consistent test state
  • Dual-layer cache verification methodology
  • Explicit testing of cache fallback mechanisms
  • Bitmap and drawable comparison techniques

Technical Details

Testing infrastructure includes:
  • JUnit 4 test framework
  • Android SDK testing utilities
  • Custom ParcelableTest and SerializableTest implementations
  • File system integration for disk cache testing
  • Memory cache instance management

Best Practices Demonstrated

The test suite exemplifies several testing best practices:
  • Proper test isolation with @Before and @After annotations
  • Comprehensive assertion coverage
  • Systematic testing of all cache operations
  • Clear test method naming conventions
  • Efficient test data setup and cleanup

blankj/androidutilcode

lib/utilcode/src/test/java/com/blankj/utilcode/util/CacheDoubleUtilsTest.java

            
package com.blankj.utilcode.util;

import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.File;
import java.io.Serializable;

import static com.blankj.utilcode.util.TestConfig.FILE_SEP;
import static com.blankj.utilcode.util.TestConfig.PATH_CACHE;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;

/**
 * <pre>
 *     author: Blankj
 *     blog  : http://blankj.com
 *     time  : 2018/06/13
 *     desc  : test CacheDoubleUtils
 * </pre>
 */
public class CacheDoubleUtilsTest extends BaseTest {

    private static final String           CACHE_PATH         = PATH_CACHE + "double" + FILE_SEP;
    private static final File             CACHE_FILE         = new File(CACHE_PATH);
    private static final byte[]           BYTES              = "CacheDoubleUtils".getBytes();
    private static final String           STRING             = "CacheDoubleUtils";
    private static final JSONObject       JSON_OBJECT        = new JSONObject();
    private static final JSONArray        JSON_ARRAY         = new JSONArray();
    private static final ParcelableTest   PARCELABLE_TEST    = new ParcelableTest("Blankj", "CacheDoubleUtils");
    private static final SerializableTest SERIALIZABLE_TEST  = new SerializableTest("Blankj", "CacheDoubleUtils");
    private static final Bitmap           BITMAP             = Bitmap.createBitmap(100, 100, Bitmap.Config.RGB_565);
    private static final Drawable         DRAWABLE           = new BitmapDrawable(Utils.getApp().getResources(), BITMAP);
    private static final CacheMemoryUtils CACHE_MEMORY_UTILS = CacheMemoryUtils.getInstance();
    private static final CacheDiskUtils   CACHE_DISK_UTILS   = CacheDiskUtils.getInstance(CACHE_FILE);
    private static final CacheDoubleUtils CACHE_DOUBLE_UTILS = CacheDoubleUtils.getInstance(CACHE_MEMORY_UTILS, CACHE_DISK_UTILS);

    static {
        try {
            JSON_OBJECT.put("class", "CacheDiskUtils");
            JSON_OBJECT.put("author", "Blankj");
            JSON_ARRAY.put(0, JSON_OBJECT);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Before
    public void setUp() {
        CACHE_DOUBLE_UTILS.put("bytes", BYTES);
        CACHE_DOUBLE_UTILS.put("string", STRING);
        CACHE_DOUBLE_UTILS.put("jsonObject", JSON_OBJECT);
        CACHE_DOUBLE_UTILS.put("jsonArray", JSON_ARRAY);
        CACHE_DOUBLE_UTILS.put("bitmap", BITMAP);
        CACHE_DOUBLE_UTILS.put("drawable", DRAWABLE);
        CACHE_DOUBLE_UTILS.put("parcelable", PARCELABLE_TEST);
        CACHE_DOUBLE_UTILS.put("serializable", SERIALIZABLE_TEST);
    }

    @Test
    public void getBytes() {
        assertEquals(STRING, new String(CACHE_DOUBLE_UTILS.getBytes("bytes")));
        CACHE_MEMORY_UTILS.remove("bytes");
        assertEquals(STRING, new String(CACHE_DOUBLE_UTILS.getBytes("bytes")));
        CACHE_DISK_UTILS.remove("bytes");
        assertNull(CACHE_DOUBLE_UTILS.getBytes("bytes"));
    }

    @Test
    public void getString() {
        assertEquals(STRING, CACHE_DOUBLE_UTILS.getString("string"));
        CACHE_MEMORY_UTILS.remove("string");
        assertEquals(STRING, CACHE_DOUBLE_UTILS.getString("string"));
        CACHE_DISK_UTILS.remove("string");
        assertNull(CACHE_DOUBLE_UTILS.getString("string"));
    }

    @Test
    public void getJSONObject() {
        assertEquals(JSON_OBJECT.toString(), CACHE_DOUBLE_UTILS.getJSONObject("jsonObject").toString());
        CACHE_MEMORY_UTILS.remove("jsonObject");
        assertEquals(JSON_OBJECT.toString(), CACHE_DOUBLE_UTILS.getJSONObject("jsonObject").toString());
        CACHE_DISK_UTILS.remove("jsonObject");
        assertNull(CACHE_DOUBLE_UTILS.getJSONObject("jsonObject"));
    }

    @Test
    public void getJSONArray() {
        assertEquals(JSON_ARRAY.toString(), CACHE_DOUBLE_UTILS.getJSONArray("jsonArray").toString());
        CACHE_MEMORY_UTILS.remove("jsonArray");
        assertEquals(JSON_ARRAY.toString(), CACHE_DOUBLE_UTILS.getJSONArray("jsonArray").toString());
        CACHE_DISK_UTILS.remove("jsonArray");
        assertNull(CACHE_DOUBLE_UTILS.getJSONArray("jsonArray"));
    }

    @Test
    public void getBitmap() {
        String bitmapString = "Bitmap (100 x 100) compressed as PNG with quality 100";
        assertEquals(BITMAP, CACHE_DOUBLE_UTILS.getBitmap("bitmap"));
        CACHE_MEMORY_UTILS.remove("bitmap");
        assertArrayEquals(
                ImageUtils.bitmap2Bytes(BITMAP, Bitmap.CompressFormat.PNG, 100),
                ImageUtils.bitmap2Bytes(CACHE_DOUBLE_UTILS.getBitmap("bitmap"), Bitmap.CompressFormat.PNG, 100)
        );
        CACHE_DISK_UTILS.remove("bitmap");
        assertNull(CACHE_DOUBLE_UTILS.getBitmap("bitmap"));
    }

    @Test
    public void getDrawable() {
        String bitmapString = "Bitmap (100 x 100) compressed as PNG with quality 100";
        assertEquals(DRAWABLE, CACHE_DOUBLE_UTILS.getDrawable("drawable"));
        CACHE_MEMORY_UTILS.remove("drawable");
        assertArrayEquals(
                ImageUtils.bitmap2Bytes(BITMAP, Bitmap.CompressFormat.PNG, 100),
                ImageUtils.drawable2Bytes(CACHE_DOUBLE_UTILS.getDrawable("drawable"), Bitmap.CompressFormat.PNG, 100)
        );
        CACHE_DISK_UTILS.remove("drawable");
        assertNull(CACHE_DOUBLE_UTILS.getDrawable("drawable"));
    }

    @Test
    public void getParcel() {
        assertEquals(PARCELABLE_TEST, CACHE_DOUBLE_UTILS.getParcelable("parcelable", ParcelableTest.CREATOR));
        CACHE_MEMORY_UTILS.remove("parcelable");
        assertEquals(PARCELABLE_TEST, CACHE_DOUBLE_UTILS.getParcelable("parcelable", ParcelableTest.CREATOR));
        CACHE_DISK_UTILS.remove("parcelable");
        assertNull(CACHE_DOUBLE_UTILS.getParcelable("parcelable", ParcelableTest.CREATOR));
    }

    @Test
    public void getSerializable() {
        assertEquals(SERIALIZABLE_TEST, CACHE_DOUBLE_UTILS.getSerializable("serializable"));
        CACHE_MEMORY_UTILS.remove("serializable");
        assertEquals(SERIALIZABLE_TEST, CACHE_DOUBLE_UTILS.getSerializable("serializable"));
        CACHE_DISK_UTILS.remove("serializable");
        assertNull(CACHE_DOUBLE_UTILS.getSerializable("serializable"));
    }

    @Test
    public void getCacheDiskSize() {
        assertEquals(FileUtils.getLength(CACHE_FILE), CACHE_DOUBLE_UTILS.getCacheDiskSize());
    }

    @Test
    public void getCacheDiskCount() {
        assertEquals(8, CACHE_DOUBLE_UTILS.getCacheDiskCount());
    }

    @Test
    public void getCacheMemoryCount() {
        assertEquals(8, CACHE_DOUBLE_UTILS.getCacheMemoryCount());
    }

    @Test
    public void remove() {
        assertNotNull(CACHE_DOUBLE_UTILS.getString("string"));
        CACHE_DOUBLE_UTILS.remove("string");
        assertNull(CACHE_DOUBLE_UTILS.getString("string"));
    }

    @Test
    public void clear() {
        assertNotNull(CACHE_DOUBLE_UTILS.getBytes("bytes"));
        assertNotNull(CACHE_DOUBLE_UTILS.getString("string"));
        assertNotNull(CACHE_DOUBLE_UTILS.getJSONObject("jsonObject"));
        assertNotNull(CACHE_DOUBLE_UTILS.getJSONArray("jsonArray"));
        assertNotNull(CACHE_DOUBLE_UTILS.getBitmap("bitmap"));
        assertNotNull(CACHE_DOUBLE_UTILS.getDrawable("drawable"));
        assertNotNull(CACHE_DOUBLE_UTILS.getParcelable("parcelable", ParcelableTest.CREATOR));
        assertNotNull(CACHE_DOUBLE_UTILS.getSerializable("serializable"));
        CACHE_DOUBLE_UTILS.clear();
        assertNull(CACHE_DOUBLE_UTILS.getBytes("bytes"));
        assertNull(CACHE_DOUBLE_UTILS.getString("string"));
        assertNull(CACHE_DOUBLE_UTILS.getJSONObject("jsonObject"));
        assertNull(CACHE_DOUBLE_UTILS.getJSONArray("jsonArray"));
        assertNull(CACHE_DOUBLE_UTILS.getBitmap("bitmap"));
        assertNull(CACHE_DOUBLE_UTILS.getDrawable("drawable"));
        assertNull(CACHE_DOUBLE_UTILS.getParcelable("parcelable", ParcelableTest.CREATOR));
        assertNull(CACHE_DOUBLE_UTILS.getSerializable("serializable"));
        assertEquals(0, CACHE_DOUBLE_UTILS.getCacheDiskSize());
        assertEquals(0, CACHE_DOUBLE_UTILS.getCacheDiskCount());
        assertEquals(0, CACHE_DOUBLE_UTILS.getCacheMemoryCount());
    }

    @After
    public void tearDown() {
        CACHE_DOUBLE_UTILS.clear();
    }

    static class ParcelableTest implements Parcelable {
        String author;
        String className;

        public String getAuthor() {
            return author;
        }

        public void setAuthor(String author) {
            this.author = author;
        }

        public String getClassName() {
            return className;
        }

        public void setClassName(String className) {
            this.className = className;
        }

        ParcelableTest(String author, String className) {
            this.author = author;
            this.className = className;
        }

        ParcelableTest(Parcel in) {
            author = in.readString();
            className = in.readString();
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(author);
            dest.writeString(className);
        }

        @Override
        public int describeContents() {
            return 0;
        }

        public static final Creator<ParcelableTest> CREATOR = new Creator<ParcelableTest>() {
            @Override
            public ParcelableTest createFromParcel(Parcel in) {
                return new ParcelableTest(in);
            }

            @Override
            public ParcelableTest[] newArray(int size) {
                return new ParcelableTest[size];
            }
        };

        @Override
        public boolean equals(Object obj) {
            return obj instanceof ParcelableTest
                    && ((ParcelableTest) obj).author.equals(author)
                    && ((ParcelableTest) obj).className.equals(className);
        }
    }

    static class SerializableTest implements Serializable {

        private static final long serialVersionUID = -5806706668736895024L;

        String author;
        String className;

        SerializableTest(String author, String className) {
            this.author = author;
            this.className = className;
        }

        public String getAuthor() {
            return author;
        }

        public void setAuthor(String author) {
            this.author = author;
        }

        public String getClassName() {
            return className;
        }

        public void setClassName(String className) {
            this.className = className;
        }

        @Override
        public boolean equals(Object obj) {
            return obj instanceof SerializableTest
                    && ((SerializableTest) obj).author.equals(author)
                    && ((SerializableTest) obj).className.equals(className);
        }
    }
}