android - 模拟 Android AssetManager

标签 android unit-testing mockito

我有一段代码接受 Context 并将此上下文传递给私有(private)方法。 私有(private)方法调用 getAssets().open() 来读取存在于我的应用程序 Assets 文件夹中的文件。

public void methodA(Context ctx) throws IOException{
     // do some stuff here...
     Object data[] = getFileContents(ctx);
     // use the data[] returned here...

}

private Object[] getFileContents(Context ctx) throws IOException{
     Object[] data;
     BufferedInputStream is = new BufferedInputStream(context.getAssets().open("test.txt"));
     // parse file and create array of Objects[]
     return data[];
}

我正在编写单元测试以使用 Mockito 测试 methodA(),以便我可以测试传递垃圾数据或在我的测试用例中抛出异常。

问题是我无法在 Android 中模拟 AssetManager 类(它是 Final)。

我尝试使用 InstrumentationTestCase 注入(inject)真实和测试上下文,但这只适用于少数场景。 我如何控制 BufferedInputStream 以便我可以向它提供我想要的任何输入(使用模拟或其他方式)?

最佳答案

我不得不处理同样的问题。这就是我在不使用 Instrumentation 测试的情况下设法从我的单元测试程序访问配置文件的方法。 (我使用的是 Android Studio 2.1)。

单元测试代码:

public class ParametersTest {

    Parameters parameters = null;

    @Mock
    Context context;
    @Mock
    AssetManager assetManager;
    @Mock
    InputStream inputStream;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);//create all @Mock objetcs
        doReturn(assetManager).when(context).getAssets();
        //parametersandroid.xml is located in test/resources directory
        //parametersandroid.xml does not refer to a DTD file configuration.dtd
        //get the full path name of the file
        URL resource = ParametersTest.class.getClassLoader().getResource("parametersandroid.xml");
        // to be used  MyClass
        // inside the method I want to be tested there is this statement :
        // InputStream inputStream = this.assetManager.open(xmlFile);
        InputStream inputStream=new FileInputStream(resource.getPath());
        doReturn(inputStream).when(assetManager).open(anyString());
       // AssetManager assetManager = context.getAssets();
       // parameters = new Parameters(assetManager, resource.getPath());
        parameters = new Parameters(context, resource.getPath());

    }
    @Test
    public void testExtract() throws Exception {
       assertEquals(parameters.extract("//database/index[@name='TeamNameIdx']/create").replaceAll("[^a-z,A-Z,;,.,?,']", ""),"createindexTeamNameIdxonTeamEntnameasc;");
    }
}

待测类代码:

public class Parameters extends fr.acnice.valade.eric.gemara.utilities.Parameters {
    private AssetManager assetManager = null;

    public Parameters(Context context, String xmlFile) {
        super(xmlFile);
        this.assetManager = context.getAssets();
    }
    @Override
    public String extract(String request) throws XPathExpressionException,
            Exception {
        InputStream inputStream = this.assetManager.open(super.xmlFile);
        String result = (String) xPath.evaluate(request, new InputSource(inputStream),
                XPathConstants.STRING);
        if (result.isEmpty()) {
            throw new Exception(
                    "Xpath result empty !!! check configuration file");
        }
        return result;
    }

}

关于android - 模拟 Android AssetManager,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32407178/

相关文章:

android - 检查类是 fragment 还是 Activity

java - 在 Android 上下载的视频只能从应用程序播放

RestTemplate 和 RetryTemplate 的 JAVA Mockito 单元测试

android - 验证 Mockito 中的列表参数列表

java - 单元测试抛出异常

java - Rxjava 为什么 Schedulers.trampoline() 命名为 'trampoline' ?

Android Gradle 检测是发布版本还是不在运行时?

php - 如何使用 PHPUnit 测试确切的异常消息,而不是子字符串?

c# - 我如何在核心 web api 中测试我的数据注释字段?

java - 当方法使用 ObjectMapper.writeValueAsString 时如何使用模拟编写单元测试