Mockito + Dexmaker на Android

Я пытаюсь использовать Mockito в моем проекте Android. Я нашел очень хороший учебник, который занимается этим: http://www.paulbutcher.com/2012/05/mockito-on-android-step-by-step/

В основном он использует новую версию Mockito + Dexmaker и все работает как положено.
Тем не менее, когда я пытаюсь смоделировать какой-то конкретный объект Android, т.е.

Context context = mock(Context.class);

Я получаю это исключение:

java.lang.IllegalArgumentException: 
    dexcache == null (and no default could be found; 
    consider setting the 'dexmaker.dexcache' system property)
at com.google.dexmaker.DexMaker.generateAndLoad(DexMaker.java:359)
at com.google.dexmaker.stock.ProxyBuilder.buildProxyClass(ProxyBuilder.java:252)
at com.google.dexmaker.mockito.DexmakerMockMaker.createMock(DexmakerMockMaker.java:54)
at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:26)

Есть идеи как это исправить?

6 ответов

Решение

Из комментария @rjath к ответу @MrChaz это работает лучше для меня:

System.setProperty(
    "dexmaker.dexcache",
    getInstrumentation().getTargetContext().getCacheDir().getPath());

Я положил это в свой setUp() метод.

Мне удалось собрать воедино исправление, которое, кажется, работает для меня. К манифесту я добавил внешнее хранилище для чтения и записи. К тесту я добавил System.setProperty("dexmaker.dexcache", "/sdcard"); к тесту. К образу эмулятора я добавил SD-карту.

Я считаю, что это работает, потому что по умолчанию mockito пытается использовать каталог кэша приложений, но я никогда не запускаю действия, поэтому я подозреваю, что каталог никогда не создается ОС

Таким образом, проблема в том, что Dexmaker не может найти путь кеша на Android >= 4.3, как упоминали другие люди, и как описано в этой проблеме dexmaker.

Я пошел с реализацией обходного пути в специализированном инструментальном тестере, а не в каждом тесте (или их суперклассе) setUp()потому что он кажется немного менее хакерским (на самом деле он находится только в одном месте - и не унаследован в каждом подклассе) и более гибким. Ради документации это необходимые изменения, чтобы сделать это:

public class CustomInstrumentationTestRunner extends InstrumentationTestRunner {

    @Override public void onCreate (final Bundle arguments) {
        super.onCreate(arguments);

        // temporary workaround for an incompatibility in current dexmaker (1.1) implementation and Android >= 4.3
        // cf. https://code.google.com/p/dexmaker/issues/detail?id=2 for details
        System.setProperty("dexmaker.dexcache", getTargetContext().getCacheDir().toString());
    }
}

И настройте свой проект (или тестовый проект), чтобы использовать этот класс в качестве инструментированного AndroidManifest.xml при сборке с муравьем:

<instrumentation
    android:name="my.package.CustomInstrumentationTestRunner"
    android:targetPackage="my.target.package" />

или его build.gradle при сборке с Gradle:

android {
    defaultConfig {
        // ...
        testInstrumentationRunner 'my.package.CustomInstrumentationTestRunner'
    }
    // ...
}

Если у вас есть другие instrumentation записи, вы можете переключаться между ними либо в командной строке, либо выбрать один в вашей рабочей конфигурации IDE.

У меня была эта проблема для проекта библиотеки Android, но НЕ для проекта приложения! Установка системного свойства "dexmaker.dexcache", как упомянуто выше, обошла проблему. У меня устройство Android 4.3 Nexus 4, сборка с инструментами 19.0.3, target api 19, мои зависимости:

androidTestCompile "org.mockito:mockito-core:1.9.5"
androidTestCompile "com.google.dexmaker:dexmaker:1.0"
androidTestCompile "com.google.dexmaker:dexmaker-mockito:1.0"

Похоже, проект dexmaker перешел с Google Code на GitHub.

В центральном репозитории maven есть версии 1.1 и 1.2, опубликованные в марте 2014 года и декабре 2014 года.

Я подтвердил, что эта проблема "dexcache == null" все еще существует в версии 1.2 - но только на некоторых устройствах. Например, у Galaxy S5 с Android 5.0 есть проблема, а у Galaxy S4 с Android 4.4.2 нет.

Я клонировал GitHub-репозиторий ( последний коммит 12 марта 2015 - ca74669) и работал локально, и проблема была исправлена ​​(в истории также есть коммиты, которые поддерживают это). Так что, как только выйдет версия 1.3, надеюсь, эта проблема исчезнет!

Любой, кто хочет запустить локальную копию 1.3-SNAPSHOT, вот как я это сделал (на Mac, но и на других платформах должно работать, вам понадобятся mvn, adb и dx на PATH):

  1. git clone https://github.com/crittercism/dexmaker.git
  2. cd dexmaker
  3. mvn install -Dmaven.test.skip=true
  4. cp -R ~/.m2/repository/com/google/dexmaker $ANDROID_HOME/extras/android/m2repository/com/google
  5. Затем измените версию в app/build.gradle: androidTestCompile 'com.google.dexmaker:dexmaker:1.3-SNAPSHOT'
    • Или же pom.xml если вы используете maven для создания или перезаписи libs/dexmaker.jar с ~/.m2/repository/com/google/dexmaker/dexmaker/1.3-SNAPSHOT/dexmaker-1.3-SNAPSHOT.jar если вы используете eclipse/ant

Кроме того, к вашему сведению, оригинальный отчет о проблеме для той же проблемы в Google Code.

Вместо этого вы можете добавить ядро ​​mockito в качестве зависимости. Тогда эта ошибка не произойдет, и вам не понадобится обходной путь.

dependencies {
   ... 
   testCompile 'org.mockito:mockito-core:1.10.19'
}

Я наблюдал эту проблему при манипуляциях с ресурсами и папками внутри testпапка. На самом деле помог просто перезапуск Android Studio. Просто, но сработало.

Другие вопросы по тегам