Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/207.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在Android JUnit测试中加载本机库_Java_Android_Junit_Android Ndk - Fatal编程技术网

Java 在Android JUnit测试中加载本机库

Java 在Android JUnit测试中加载本机库,java,android,junit,android-ndk,Java,Android,Junit,Android Ndk,我已经使用ndk build生成了一个本机库,我可以在Android应用程序中加载并使用它。但是,我想针对我的应用程序的这一部分编写一些测试 在测试中调用本机函数时,我收到以下异常消息: java.lang.UnsatisfiedLinkError: no process in java.library.path …其中process是要导入的本机库,名为libprocess.so 我正在使用RoboeElectric进行测试,并使用RobolectrictTestRunner运行这个特定的测

我已经使用
ndk build
生成了一个本机库,我可以在Android应用程序中加载并使用它。但是,我想针对我的应用程序的这一部分编写一些测试

在测试中调用本机函数时,我收到以下异常消息:

java.lang.UnsatisfiedLinkError: no process in java.library.path
…其中
process
是要导入的本机库,名为
libprocess.so

我正在使用RoboeElectric进行测试,并使用
RobolectrictTestRunner
运行这个特定的测试,如果它有区别的话

如何让我的测试项目“查看”本机库


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

static {
    System.loadLibrary("process");
}
public static native int[] process(double[][] data);
调用
Process.Process(array)
在应用程序中工作正常(库已加载),但在从测试运行时失败,上面给出了异常


编辑2: 如果我将
-Djava.library.path=”“
设置为VM参数,则:

System.out.println(System.getProperty("java.library.path"));
确实显示了我设置的路径,但我仍然得到相同的异常。我正在将目录设置为:

<project-name>/libs/x86
/libs/x86

…但作为一个绝对路径。

我已切换到默认测试样式(使用ActivityUnitTestCase而不是RoboElectric),现在运行良好。很遗憾,我不得不牺牲测试运行的速度,但在模拟器上运行测试实际上是可行的。您还可以为JNI类创建一个影子类,如下所述:


也许为我的机器编译库会起作用,但我不能再花更多的时间在上面了。

以防万一,对于其他寻找解决方案的人来说,有一种方法可以正确设置JUnit测试的库查找路径(尽管我仍然没有成功运行测试,但存在不同的问题):

需要将路径放入
LD_LIBRARY\u path
(或Windows上的
path
)环境变量中。我有完全相同的经验:我先设置
java.LIBRARY.path
,但它似乎不会以任何方式影响本机加载程序的行为


如果您需要有关如何使用Gradle/Android Studio实现这一点的详细信息,欢迎您查看。对于仍在寻找的人,blork有一个正确的想法-您需要为您的“本机”平台(Windows、Linux、Mac)编译本机库。安卓NDK为Android平台构建库(.so文件-可能也适用于Linux),这就是为什么在活动测试用例中运行时没有问题(因为它加载了一个Android实例)

要运行低级的hella fast JUnit测试,您需要支持JVM。在Windows上,这可能是在构建DLL,在Apple上,这是在构建dylibs(假设共享库)

我刚刚在android ndk swig示例repo()中完成了一个示例

基本上,在我的CmakeList中,我添加了一个苹果警告:

# 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})
然后我确保Gradle运行单元测试,但使用Mac构建系统(而不是NDK)

警告时间

当您使用此方法时,从技术上讲,您不是在测试NDK生成的LIB。您是在测试相同的代码,而是使用不同的编译器(msvc、xcode、gcc、clang,以及您在主机上使用的任何编译器)进行编译

这实际上意味着,大多数测试结果都是有效的——除非你遇到由每个编译器的怪癖或STL实现等引起的问题……这并不像10多年前那么糟糕,但你不能100%肯定地说JUnit使用主机libs测试的结果与安卓libs相同不过,有人说这相当接近

再说一次,除非您正在为每个受支持的体系结构使用Android NDK运行您的本机单元测试,否则您也不能说任何关于确定性的事情……所以从中获取您想要的

一种过火的方法(但如果是自动化的话,那真的很酷)是编写您的本机单元测试(Google测试、Catch等),然后使用每个体系结构的Android NDK编译并运行您的本机LIB和单元测试。这为您的潜在目标体系结构提供了C/C++覆盖范围

从这里开始,您可以使用前面提到的主机库和JUnit来快速单元测试与本机库交互的JNI层。在您的CI系统中,您可能仍然应该运行这些相同的单元测试,但作为Android插装测试(或运行模拟Android环境的其他测试)

与所有东西一样,无论您在哪里拥有接口,都可以创建模拟——但在某些时候,您也需要进行系统/功能/集成测试

更新:


在博客文章()中对上述内容进行更全面的解释。

您的包名正确吗?您如何加载库?我已添加到我的问题中,请参见上文。您是否可以使用以下内容进行测试:
-Djava.library.path=“”
?Thakns感谢您的帮助,但将其添加到“VM参数”中在Eclipse下,运行配置选项会给我留下同样的错误。您是否使用任何存储库?我是否有可能看到您的代码?为了在Windows上获得它,我应该做哪些更改?(64位)@Pregunton好吧,可能大部分构建脚本都是用*nix样式的参数和目录结构设置的。你必须在路径中设置cmake,然后设置正确的Windows命令行调用。我相信有一种跨平台的方法可以做到这一点。CmakeList可能还需要一些调整-只是无法重新调用l因为我几年前就这么做了。我喜欢这个答案,并想添加一个更正。Android NDK为Android平台构建库(.so文件-可能也可以在Linux上工作),>>这不是真的。纯平台特定的,如x86或ARM或其他平台也是如此。
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
    }
 }