【问题标题】:Is there any way to mock JNI methods in my android project to do Junit testing?有什么方法可以在我的 android 项目中模拟 JNI 方法来进行 Junit 测试?
【发布时间】:2014-03-17 04:48:31
【问题描述】:

您好,我需要为一个 Android 项目编写 Junit 测试,但它具有 JNI 方法,因为它使用 webkit。有什么方法可以测试这些 android 方法(我不想测试 JNI 方法)。

就像:

public void androidMethod(){

//some android code

  nativeInit();    //how do I mock such methods?

//some code again
}

我尝试过 powermock、easymock、roboelectric,但没有成功。请帮助我。

【问题讨论】:

  • 方法必须是本地的吗?只需创建一个与本机方法执行相同操作的 Java 对象。
  • 嘿,感谢您的帮助。但是我无法更改源代码中的任何内容! :/还有其他方式吗?
  • powermock 有什么问题?您应该向我们展示您的尝试。

标签: java android unit-testing junit java-native-interface


【解决方案1】:

我昨天发现我可以用 Mockito 解决这个问题(我没有尝试 powermock 或 easymock)。假设你的班级是 C 班,我的解决方案是:

C c=spy(new C); 
doNothing().when(c).nativeInit();
c.androidMethod()
verify(c).nativeInit();

当然,这要求 nativeInit 对测试可见。

【讨论】:

    【解决方案2】:

    类似的问题

    虽然我已经在 src/test 下的 JUnit 测试中使用了 mockito,但我遇到了同样的问题事件。在src/androidTest 下添加测试后,我开始遇到问题,包括这次崩溃:

    Mockito 无法模拟/监视,因为:
    - 最后一课

    在手动创建 open 类之后,我仍然在 JNI 层中遇到崩溃,因为它试图加载 *.so 库(如果模拟正常工作就不会发生这种情况)。

    工作解决方案

    相反,我必须打开课程使用Kotlin's all-open plugin进行测试。 this recent medium post 中也很好地解释了该过程,但归结为以下四个简单的更改,这些更改也在 one of the architecture components sample apps 中建模:

    1. 将这些添加到 build.gradle:

        buildscript {
            dependencies {
                classpath "org.jetbrains.kotlin:kotlin-allopen:${versions.kotlin}"
            }
        }
    
        apply plugin: "kotlin-allopen"
    
        allOpen {
            // marker for classes that we want to be able to extend in debug builds
            annotation 'com.your.package.name.OpenClass'
        }
    
    

    2. 在调试风格中添加corresponding annotations。例如:app/src/debug/java/com/your/package/name/OpenForTesting.kt

    package com.your.package.name
    
    @Target(AnnotationTarget.ANNOTATION_CLASS)
    annotation class OpenClass
    
    @OpenClass
    @Target(AnnotationTarget.CLASS)
    annotation class OpenForTesting
    
    

    3. 在发布风格中添加corresponding annotation。例如:app/src/release/java/com/your/package/name/OpenForTesting.kt

    package com.your.package.name
    
    @Target(AnnotationTarget.CLASS)
    annotation class OpenForTesting
    
    

    4.在需要模拟的类中添加@OpenForTesting注解

    package com.your.package.name
    
    @OpenForTesting
    class JniClassOfVictory {
        ...
        external fun nativeInit()
        ...
        companion object {
            init {
                System.loadLibrary("victoryeveryday")
            }
        }
    }
    
    

    结果是一种将类标记为打开的灵活方式,而无需在发布版本中实际打开它们。当然,这是因为我们在release中创建的@OpenForTesting注解没有用@OpenClass标记,但是在debug中同样的注解是用@OpenClass标记。在build.gradle 中,我们将该注释指定为kotlin-allopen 插件的信号。因此,任何带有 @OpenForTesting 注释的类都将在编译时打开,但仅在 Debug 构建时打开。

    【讨论】:

      猜你喜欢
      • 2011-02-22
      • 2016-07-18
      • 1970-01-01
      • 1970-01-01
      • 2021-03-06
      • 1970-01-01
      • 1970-01-01
      • 2013-04-26
      • 1970-01-01
      相关资源
      最近更新 更多