JaCoCo + Mockito + Android测试:零覆盖报告

时间:2017-10-01 22:24:41

标签: android android-gradle mockito jacoco android-instrumentation

我知道这个主题有很多问题(和答案),但我已经尝试过在SO和其他网站上找到的所有内容,但我还没有找到一种方法让JaCoCo包括使用Mockito的Android测试。

我的问题: 我想使用JaCoCo生成单元测试和仪器测试(androidTest)的代码覆盖。我使用Mockito来模拟一些课程。我在GitHub中找到了一个使用JaCoCo的样本并将其用作起点。

https://github.com/rafaeltoledo/unified-code-coverage-android

当我运行该示例中包含的自定义jacocoTestReport任务时,代码覆盖率报告已正确生成,代码覆盖率为100%。该报告包括单元测试和android测试。但是,该示例未使用Mockito(我需要),因此我将以下内容添加到app / build.gradle

dependencies {
 ...
 androidTestCompile 'org.mockito:mockito-android:2.10.0'
}

我在app / src / main / java / net / rafaeltoledo / coverage / Util.java中添加了一个名为Util的非常简单的Java类

public class Util {
    public int anIntMethod() {
        return 0;
    }
}

并将以下简单测试添加到app / src / androidTest / java / net / rafaeltoledo / coverage / MainActivityTest.java中的现有android测试

@Test
public void utilMethod() {
    Util util = Mockito.mock(Util.class);
    Mockito.doReturn(10).when(util).anIntMethod();
    assertThat(util.anIntMethod(), is(10));
}

当我再次运行jacocoTestReport时,代码覆盖率降至88%,并且报告实际上显示我的测试未涵盖Util类,即使我显然有一个练习该类的测试。

(我想添加报告的截图,但我没有足够的声誉,所以这里是coverage report and execution report的链接,表明两个测试实际上都已执行了)

版本信息: Gradle插件:2.3.3 Jacoco:0.7.8.201612092310 Android Studio:2.3.3 Android构建工具:25.0.2

这是Jacoco限制还是我做错了什么?

1 个答案:

答案 0 :(得分:5)

  我做错了吗?

让我们放下Android,因为IMO显然对你对核心事物的期望/理解有些不对劲 - 嘲笑:

  

即使我显然有一个练习该课程的测试。

通过

@Test
public void utilMethod() {
    Util util = Mockito.mock(Util.class);
    Mockito.doReturn(10).when(util).anIntMethod();
    assertThat(util.anIntMethod(), is(10));
}

您没有对anIntMethod进行测试,无论10中实际写入的是什么,您都在测试始终返回anIntMethod的内容。

Coverage显示已执行的内容,因此绝对正确anIntMethod为零,因为它未执行。

模拟用于将测试中的类与其依赖项隔离,但不能替换它,否则您不会测试实际代码。

以下是正确使用模拟的示例:

src/main/java/Util.java

public class Util {
  int anIntMethod(Dependency d) {
    return d.get();
  }
}
class Dependency {
  int get() {
    return 0;
  }
}

src/test/java/UtilTest.java

import org.junit.Test;
import org.mockito.Mockito;

import static org.junit.Assert.assertEquals;

public class UtilTest {
  @Test
  public void utilMethod() {
    Dependency d = Mockito.mock(Dependency.class);
    Mockito.doReturn(10).when(d).get();
    assertEquals(10, new Util().anIntMethod(d));
  }
}

build.gradle

apply plugin: "java"
apply plugin: "jacoco"

repositories {
  mavenCentral()
}

dependencies {
  testCompile "junit:junit:4.12"
  testCompile "org.mockito:mockito-core:2.10.0"
}

执行gradle build jacocoTestReport覆盖后

coverage

部分嘲笑的情况:

src/main/java/Util.java

public class Util {
  int get() {
    return 0;
  }

  int anIntMethod() {
    return get();
  }
}

src/test/java/UtilTest.java

import org.junit.Test;
import org.mockito.Mockito;

import static org.junit.Assert.assertEquals;

public class UtilTest {
  @Test
  public void utilMethod() {
    Util util = Mockito.mock(
      Util.class,
      Mockito.withSettings().defaultAnswer(Mockito.CALLS_REAL_METHODS)
    );
    Mockito.doReturn(10).when(util).get();
    assertEquals(10, util.anIntMethod());
  }
}

coverage

在这两种情况下,模拟部件都显示为未覆盖,这是正确的。