Intereting Posts

Единичный тест Класс Java, который загружает собственную библиотеку

Я запускаю модульные тесты в Android Studio. У меня есть класс Java, который загружает собственную библиотеку со следующим кодом

static { System.loadLibrary("mylibrary"); } 

Но когда я тестирую этот класс внутри моего каталога src/test я получаю

 java.lang.UnsatisfiedLinkError: no mylibrary in java.library.path at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1864) at java.lang.Runtime.loadLibrary0(Runtime.java:870) at java.lang.System.loadLibrary(System.java:1122) 

Как я могу заставить его найти путь к родным .so-библиотекам, который находится в src/main/libs для модульного тестирования без ошибок?

Примечание: внутри каталога src/main/libs меня есть еще 3 подкаталога: armeabi , mips и x86 . Каждый из них содержит правильный .so-файл. Я использую Non-экспериментальную версию для создания NDK-библиотек.

Я не хочу использовать другие сторонние библиотеки тестирования, так как все мои другие «чистые» классы Java могут быть проверены в порядке. Но если это невозможно, то я открыт для альтернатив.

Вот мой тестовый код, который выдает ошибку

  @Test public void testNativeClass() throws Exception { MyNativeJavaClass test = new MyNativeJavaClass("lalalal") List<String> results = test.getResultsFromNativeMethodAndPutThemInArrayList(); assertEquals("There should be only three result", 3, results.size()); } 

Единственное решение, которое я нашел, что работает без хаков, – это использовать JUnit с помощью инструментального тестирования (каталог androidTest). Мой класс теперь может быть протестирован отлично, но с помощью устройства android для Android.

Просто убедитесь, что каталог, содержащий библиотеку, содержится в java.library.path .

Из теста вы можете установить его перед загрузкой библиотеки:

 System.setProperty("java.library.path", "... path to the library .../libs/x86"); 

Вы можете указать путь жестко закодированным, но это сделает проект менее переносимым для других сред. Поэтому я предлагаю вам создать его программно.

Файлы .so должны быть помещены под

SRC / основные / jniLibs

Не под src / main / libs

(Протестировано с помощью Android Studio 1.2.2)

Для справки проверьте страницу – http://ph0b.com/android-studio-gradle-and-ndk-integration/ , хотя некоторые части могут быть устаревшими.

Попробуйте запустить тестовый код с параметром java -XshowSettings: properties и убедитесь, что ваш путь назначения для системных библиотек и в результате вывода этой команды значения пути к библиотеке одинаковы

Я не уверен, решает ли это вашу проблему или нет, но пока никто не упомянул о шаблоне стратегии для работы с библиотекой предварительной загрузки классов во время их создания.

Давайте посмотрим на пример:

Мы хотим реализовать класс решателя Fibonacci. Предполагая, что мы обеспечили реализацию в собственном коде и сумели создать собственную библиотеку, мы можем реализовать следующее:

 public interface Fibonacci { long calculate(int steps); } 

Во-первых, мы предоставляем нашу собственную реализацию:

 public final class FibonacciNative implements Fibonacci { static { System.loadLibrary("myfibonacci"); } public native long calculate(int steps); } 

Во-вторых, мы предоставляем реализацию Java для решения Fibonacci:

 public final class FibonacciJava implements Fibonacci { @Override public long calculate(int steps) { if(steps > 1) { return calculate(steps-2) + calculate(steps-1); } return steps; } } 

В-третьих, мы завершаем решателей родительским классом, выбирая его собственную реализацию во время его создания:

 public class FibonnaciSolver implements Fibonacci { private static final Fibonacci STRATEGY; static { Fibonacci implementation; try { implementation = new FibonnaciNative(); } catch(Throwable e) { implementation = new FibonnaciJava(); } STRATEGY = implementation; } @Override public long calculate(int steps) { return STRATEGY.calculate(steps); } } 

Таким образом, проблема с поиском пути к библиотеке с использованием стратегии. Однако этот случай не решает проблему, если на самом деле необходимо включить встроенную библиотеку во время теста. Он не решает проблему, если родная библиотека является сторонней библиотекой.

В основном, это обходит проблему загрузки загружаемой библиотеки, издеваясь над собственным кодом для Java-кода.

Надеюсь, это поможет как-то 🙂