Mockito for Environment getExternalStorageState()android

时间:2017-10-05 20:12:51

标签: java android unit-testing junit mockito

我是模拟测试的新手,我一直在尝试关注博客,但它现在非常混乱。

座右铭是在FileUtility类中测试两个静态函数。代码如下。

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();
}

我应该如何编写单元测试用例来测试该函数的输入,例如“fileName = null”?

请分享一些灯光/代码。

1 个答案:

答案 0 :(得分:3)

getLogFilePath()看起来有三条主要路径:

  • 如果外部存储可写且外部存储公共目录可用,则使用
  • 如果外部存储器是可写的且外部存储器公共目录不可用但外部存储器目录可用则使用它
  • 在所有其他情况下,请使用数据目录

编写这些测试用例只是对以下方法有一些嘲讽的期望:

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

以下是一个例子:

// 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);
    }
}

注意:

  • 这使用JUnit TemporaryFolder规则来创建(并在完成时丢弃)断言的目录。这也可以使用模拟的File实例来实现。
  • OP没有包含getAbsoluteFilePath()的定义所以我推测它是这样的:

    private static String getAbsoluteFilePath(File file, String fileName) {
        return file.getAbsolutePath() + File.separator + fileName;
    }
    
  • 上面的示例并非详尽无遗,它旨在提供足够的,以便您可以了解它的工作原理以及如何测试静态方法等。