对于仍在寻找的人来说,blork 的想法是正确的——您需要为您的“本机”平台(Windows、Linux、Mac)编译本机库。Android NDK 为 Android 平台构建库(.so 文件 - 也可能在 Linux 上运行),这就是在 Activity Test Cases 中运行没有问题的原因(因为它加载了一个 Android 实例)。
要运行低级、快速的 JUnit 测试,您需要支持 JVM。在 Windows 上,这可能正在构建 DLL,在 Apple 上,它正在构建 dylibs(假设共享库)。
我刚刚在我的 android-ndk-swig-example 存储库 ( https://github.com/sureshjoshi/android-ndk-swig-example/issues/9 ) 中完成了一个示例。
基本上,在我的 CMakeLists 中,我添加了一个 Apple 警告:
# 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)。
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
}
}
警告时间!!!
当您使用此方法时,从技术上讲,您并未测试 NDK 生成的库。您正在测试相同的代码,但使用不同的编译器(msvc、xcode、gcc、clang,无论您在主机上使用什么)编译。
这实际上意味着,大多数测试结果都是有效的——除非你遇到由每个编译器的怪癖或 STL 实现等引起的问题......这并不像 10 多年前那么糟糕,但是您不能 100% 肯定地说,使用主机库进行 JUnit 测试的结果与 Android 库相同。不过,您可以说它相当接近。
再说一次,除非您使用 Android NDK 为每个受支持的架构运行您的本机单元测试,否则您也不能说任何关于确定性的事情......所以,从它那里得到什么。
一个矫枉过正的方法(但如果自动化真的很酷)是编写你的原生单元测试,无论你做什么(谷歌测试,Catch 等),然后编译和运行你的原生库和每个架构的 Android NDK 单元测试。这为您的潜在目标架构提供了 C/C++ 覆盖。
从这里,您可以将上述主机库与 JUnit 一起使用,以快速对与您的本地库交互的 JNI 层进行单元测试。在您的 CI 系统中,您可能仍然应该运行这些相同的单元测试 - 但作为 Android Instrumentation 测试(或运行模拟 Android 环境的其他东西)。
与所有事情一样,无论您有接口,都可以创建模拟 - 但在某些时候,您也需要系统/功能/集成测试。
更新:
在博客文章中对上述内容进行了更全面的解释(http://www.sureshjoshi.com/mobile/android-junit-native-libraries/)