Vansi
Vansi

Reputation: 787

Mockito for Environment getExternalStorageState() android

I am new to mockito testing, I have been trying to follow the blogs but its pretty jumbled up for now.

The motto is to test two static functions in the FileUtility class. The code goes below.

public static boolean isExternalStorageWritable() {
    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(state)) {
        return true;
    }
    return false;
}

public static String getLogFilePath(String fileName) {
    if (isExternalStorageWritable()) {
        File _file;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            _file = Environment.getExternalStoragePublicDirectory(
                    Environment.DIRECTORY_DOCUMENTS);
            if (exists(_file)) {
                return getAbsoluteFilePath(_file,fileName);
            }
        }

        _file = Environment.getExternalStorageDirectory();
        if (exists(_file)) {
            return getAbsoluteFilePath(_file,fileName);
        }
    }

    File _file = Environment.getDataDirectory();
    if (exists(_file)) {
        return getAbsoluteFilePath(_file,fileName);
    }

    return fileName;
}

private static boolean exists(File file) {
    return file != null && file.exists();
}

How should i write the unit test case to test that function for inputs like "fileName=null"?

Please share some light/code into it.

Upvotes: 0

Views: 3976

Answers (1)

glytching
glytching

Reputation: 47985

It looks like there are three main paths through getLogFilePath():

  • If external storage is writeable and the external storage public directory is available then use it
  • If external storage is writeable and the external storage public directory is not available but the external storage directory is available then use it
  • In all other cases use the data directory

Writing these test cases just involves a few mocked expectations on the following methods:

  • Environment.getExternalStorageState()
  • Environment.getExternalStoragePublicDirectory()
  • Environment.getExternalStorageDirectory()
  • Environment.getDataDirectory()

Here's an example:

// this test case need to mock static methods so it uses PowerMock
@RunWith(PowerMockRunner.class)
// this static methods to be mocked are on Environment so that must be 'prepared'
@PrepareForTest({Environment.class})
public class StorageUtilsTest {

    @Rule
    public TemporaryFolder storageDirectory = new TemporaryFolder();

    private File nonExistentDirectory;
    private File existentDirectory;

    @Before
    public void setup() {
        nonExistentDirectory = Mockito.mock(File.class);
        Mockito.when(nonExistentDirectory.exists()).thenReturn(false);

        existentDirectory = storageDirectory.getRoot();

        PowerMockito.mockStatic(Environment.class);
    }

    @Test
    public void willUseTheExternalStoragePublicDirectoryWhenItIsAvailable() {
        // external storage is writeable
        Mockito.when(Environment.getExternalStorageState()).thenReturn(Environment.MEDIA_MOUNTED);
        // the external storage public directory is available
        Mockito.when(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS)).thenReturn(existentDirectory);

        String fileName = "someFileName";
        String logFilePath = StorageUtils.getLogFilePath(fileName);

        Assert.assertEquals(existentDirectory.getAbsolutePath() + File.separator + fileName, logFilePath);
    }

    @Test
    public void willUseTheExternalStorageDirectoryWhenItIsAvailable() {
        // external storage is writeable
        Mockito.when(Environment.getExternalStorageState()).thenReturn(Environment.MEDIA_MOUNTED);
        // the external storage public directory is not available
        Mockito.when(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS)).thenReturn(nonExistentDirectory);
        // the external storage directory is available
        Mockito.when(Environment.getExternalStorageDirectory()).thenReturn(existentDirectory);

        String fileName = "someFileName";
        String logFilePath = StorageUtils.getLogFilePath(fileName);

        Assert.assertEquals(existentDirectory.getAbsolutePath() + File.separator + fileName, logFilePath);
    }

    @Test
    public void willUseTheDataDirectoryWhenExternalStorageIsNotWriteable() {
        // external storage is not writeable
        Mockito.when(Environment.getExternalStorageState()).thenReturn("not media mounted");
        // the data directory is available
        Mockito.when(Environment.getDataDirectory()).thenReturn(existentDirectory);

        String fileName = "someFileName";
        String logFilePath = StorageUtils.getLogFilePath(fileName);

        Assert.assertEquals(existentDirectory.getAbsolutePath() + File.separator + fileName, logFilePath);
    }

    @Test
    public void willUseTheDataDirectoryWhenNothingElseIsAvailable() {
        // external storage is writeable
        Mockito.when(Environment.getExternalStorageState()).thenReturn(Environment.MEDIA_MOUNTED);
        // but neither of the external storage directories are available
        Mockito.when(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS)).thenReturn(nonExistentDirectory);
        Mockito.when(Environment.getExternalStorageDirectory()).thenReturn(nonExistentDirectory);
        // so we must fall through to the data directory
        Mockito.when(Environment.getDataDirectory()).thenReturn(existentDirectory);

        String fileName = "someFileName";
        String logFilePath = StorageUtils.getLogFilePath(fileName);

        Assert.assertEquals(existentDirectory.getAbsolutePath() + File.separator + fileName, logFilePath);
    }

    @Test
    public void doesSomethingWhenGivenANullFileName() {
        // external storage is writeable
        Mockito.when(Environment.getExternalStorageState()).thenReturn(Environment.MEDIA_MOUNTED);
        // the external storage public directory is available
        Mockito.when(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS)).thenReturn(existentDirectory);

        String logFilePath = StorageUtils.getLogFilePath(null);

        // the assertion here will depend on what your getAbsoluteFilePath() method does with a null file name!
        Assert.assertEquals(existentDirectory.getAbsolutePath() + File.separator, logFilePath);
    }
}

Notes:

  • This uses the JUnit TemporaryFolder Rule to create (and discard on completion) a directory for the assertions. This could also be implemented using a mocked File instance.
  • The OP did not include a definition of getAbsoluteFilePath() so I presumed it was something like this:

    private static String getAbsoluteFilePath(File file, String fileName) {
        return file.getAbsolutePath() + File.separator + fileName;
    }
    
  • The above example is not intended to be exhaustive, it is intended to provide just enough so that you can understand how it works and how to test static methods etc

Upvotes: 4

Related Questions