2015-09-04 2 views
3

У меня есть часть кода, которая принимает контекст и передает этот контекст частному методу. Закрытый метод вызывает getAssets(). Open(), чтобы прочитать файл, присутствующий в папке с ресурсами моего приложения.Mocking Android AssetManager

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[]; 
} 

Я пишу юнит-тесты, чтобы проверить Methoda() с помощью Mockito, так что я могу проверить передачу данных барахла или бросать исключения в моих testcases.

Проблема в том, что я не могу издеваться над классом AssetManager в android (он является окончательным).

Я попытался использовать InstrumentationTestCase для ввода реального и тестового контекста, но это работает только для нескольких сценариев. Как управлять BufferedInputStream, чтобы я мог предоставить ему любой вход, который я хочу (используя mocks или иначе)?

ответ

6

Мне приходилось иметь дело с той же проблемой. Так мне удалось получить доступ к конфигурационному файлу из моей тестовой программы без использования теста 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; 
    } 

} 
0

Попробуйте извлекая context по телефону коды ниже:

Context context = InstrumentationRegistry.getTargetContext(); 
BufferedInputStream is = new BufferedInputStream(context.getAssets().open("test.txt")); 
Смежные вопросы