在Android JUnit测试加载本地库(Loading a native library in

2019-09-03 01:45发布

我已经使用生成的本地库ndk-build它,我能够加载并在我的Android应用程序中使用。 不过,我想对写我的应用程序,这部分的一些测试。

当调用在我的测试本机的功能,我收到此异常消息:

java.lang.UnsatisfiedLinkError: no process in java.library.path

...其中process是我的本地库导入,命名libprocess.so

我使用Roboelectric我的测试,并运行这个特殊的一个与RobolectricTestRunner ,如果它的确与众不同。

我怎样才能得到我的测试项目,以“看到”本地库?


编辑:我加载库在我的应用程序,如下所示:

static {
    System.loadLibrary("process");
}
public static native int[] process(double[][] data);

调用Process.process(array)工作在应用程序(库被加载)的罚款,但是从上面给出的异常运行测试时失败。


编辑2:如果我设置-Djava.library.path="<the directory of libprocess.so>"作为VM参数,则:

System.out.println(System.getProperty("java.library.path"));

确实显示我设置的路径,但我仍然得到同样的异常。 我设置的目录如下:

<project-name>/libs/x86

......但作为一个绝对路径。

Answer 1:

对于任何人还在找,blork有正确的想法 - 你需要编译你的本机库为您的“天然”平台(Windows,Linux,苹果)。 而Android NDK构建Android平台库(.so文件 - 还可以在Linux上工作),这就是为什么在活动测试用例运行(因为它加载了一个Android实例)没有问题。

为了获得低的水平,运行速度快海拉JUnit测试,你需要支持你的JVM。 在Windows中,这可能是生成DLL,在苹果,它的建设dylibs(假设共享库)。

我刚刚完成我的Android NDK,痛饮,例如回购(样本https://github.com/sureshjoshi/android-ndk-swig-example/issues/9 )。

基本上,我CMakeLists,我添加了一个苹果警告:

# Need to create the .dylib and .jnilib files in order to run JUnit tests
if (APPLE)
    # Ensure jni.h is found
    find_package(JNI REQUIRED)
    include_directories(${JAVA_INCLUDE_PATH})

然后,我要确保摇篮运行单元测试,但使用Mac构建系统(未NDK)。

def osxDir = projectDir.absolutePath + '/.externalNativeBuild/cmake/debug/osx/'

task createBuildDir() {
    def folder = new File(osxDir)
    if (!folder.exists()) {
        folder.mkdirs()
    }
}

task runCMake(type: Exec) {
    dependsOn createBuildDir
    workingDir osxDir // Jump to future build directory
    commandLine '/usr/local/bin/cmake' // Path from HomeBrew installation
    args '../../../../' // Relative path for out-of-source builds
}

task runMake(type: Exec) {
    dependsOn runCMake
    workingDir osxDir
    commandLine 'make'
}

 project.afterEvaluate {
    // Not sure how much of a hack this is - but it allows CMake/SWIG to run before Android Studio
    // complains about missing generated files
    // TODO: Probably need a release hook too?
    javaPreCompileDebug.dependsOn externalNativeBuildDebug
    if (org.gradle.internal.os.OperatingSystem.current().isMacOsX()) {
        javaPreCompileDebugAndroidTest.dependsOn runMake
    }
 }

CAVEAT时间!

当您使用此方法,你技术上没有测试NDK生成库。 您正在测试相同的代码,但使用不同的编译器(MSVC,Xcode中,GCC,铛,无论你在主机上使用)编制。

这意味着实际上,是大多数的测试结果将是有效的 - 当你进入由每个编译器的怪癖,或者STL实现等问题,否则......这不是那么糟糕,因为它是10+年前,但你不能100%肯定地说,与主机库的JUnit测试的结果是相同的Android的库。 你可以说,这是相当接近的,虽然。

话又说回来,除非你正在运行使用的Android NDK为每个支持的架构原生的单元测试,你也不能说肯定无论是什么...因此,采取什么你会的。

矫枉过正的做法(但真的很酷,如果自动)会,但是你做他们(谷歌测试,捕捉等)来编写本地的单元测试,然后编译时,每次使用的架构在Android NDK运行本机库和单元测试。 这提供了在你的潜在目标架构的C / C ++的覆盖范围。

从这里,你可以使用上述主机库使用JUnit迅速单元测试你的JNI层与本地库进行交互。 在你的CI系统,你应该仍然可能运行这些相同的单元测试 - 但作为Android的仪器测试(或别的东西运行一个仿真的Android环境)。

正如一切,只要你有一个接口,您可以创建嘲弄 - 但在某些时候,你需要的系统/功能/集成测试了。

更新:

在博客文章的上面更全面的解释( http://www.sureshjoshi.com/mobile/android-junit-native-libraries/ )



Answer 2:

我已经切换到默认的测试风格(使用而不是RoboElectric ActivityUnitTestCase)和它现在运行良好。 这是一个耻辱,我不得不牺牲试运行的速度,但运行在模拟器上测试实际工作。 您还可以创建一个影子类的JNI类,这里详细:

上加载JNI库应用对象Robolectric坦克。 我可以得到一个解决方法吗?

也许编译我的机器库会工作,但我无法花更多的时间就可以了。



Answer 3:

为以防万一,为别人寻找解决方案,这一点, 一种方法来正确设置JUnit测试的lib查找路径(虽然我还没有设法成功地运行测试,不同的问题):

需要把路径在LD_LIBRARY_PATH (或PATH在Windows)环境变量。 我有相同的经历:我设置java.library.path第一,但似乎它不以任何方式影响本机装载的行为。

欢迎你看看我这里的答案 ,如果你需要关于如何做到这一点与摇篮/ Android Studio中的细节



文章来源: Loading a native library in an Android JUnit test