对于仍在寻找答案的人,blork有正确的想法——您需要为自己的“本机”平台(Windows、Linux、Mac)编译本机库。Android NDK会为Android平台构建库(.so文件,也可能适用于Linux),这就是为什么在Activity测试用例中运行没有问题(因为它加载了一个Android实例)。
要运行低级别的超级快速的JUnit测试,您需要支持您的JVM。在Windows上,这可能需要构建DLL,在Apple上,需要构建dylibs(假设共享库)。
我刚刚在我的android-ndk-swig-example存储库中完成了一个示例 (https://github.com/sureshjoshi/android-ndk-swig-example/issues/9)。
基本上,在我的CMakeLists中,我加了一个Apple警告:
if (APPLE)
find_package(JNI REQUIRED)
include_directories(${JAVA_INCLUDE_PATH})
然后我确保Gradle在单元测试中运行,但使用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
commandLine '/usr/local/bin/cmake'
args '../../../../'
}
task runMake(type: Exec) {
dependsOn runCMake
workingDir osxDir
commandLine 'make'
}
project.afterEvaluate {
javaPreCompileDebug.dependsOn externalNativeBuildDebug
if (org.gradle.internal.os.OperatingSystem.current().isMacOsX()) {
javaPreCompileDebugAndroidTest.dependsOn runMake
}
}
注意!
当你使用这种方法时,你实际上并没有测试NDK生成的库。你测试的是相同的代码,但是使用不同的编译器(msvc、xcode、gcc、clang等)进行编译的结果。
从实际意义上讲,大多数测试结果都是有效的——除非你遇到由每个编译器的怪癖或STL实现引起的问题等。虽然这比10多年前要好,但是你不能以100%的确定性说使用主机库进行JUnit测试的结果与Android库完全相同。不过,你可以说它们是相当接近的。
另外,除非你为每个支持的架构使用Android NDK运行本机单元测试,否则你也无法对确定性做任何声明... 所以你需要自己权衡取舍。
一种过度的方法(但如果自动化会很酷)是按照你的方式编写本机单元测试(Google Test、Catch等),然后使用Android NDK在每个架构上编译和运行你的本机库和单元测试。这将提供你跨潜在目标架构的C/C++覆盖率。
从这里开始,你可以使用前面提到的主机库与JUnit快速单元测试JNI层与本机库的交互。在CI系统中,你仍然可能要运行这些相同的单元测试,但作为Android Instrumentation测试(或其他运行模拟Android环境的测试)。
像所有接口一样,你都可以创建mocks——但在某个时候,你还需要系统/功能/集成测试。
更新:
在博客文章中提供了以上内容的更全面解释(http://www.sureshjoshi.com/mobile/android-junit-native-libraries/)。
-Djava.library.path="<libprocess.so文件所在目录>"
? - Sam R.