JaCoCo + Mockito + Android测试:零覆盖率报告 [英] JaCoCo + Mockito + Android tests: Zero coverage reported

查看:515
本文介绍了JaCoCo + Mockito + Android测试:零覆盖率报告的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道这个主题有很多问题(和答案),但是我已经尝试了在SO和其他网站上找到的所有内容,但是我还没有找到让JaCoCo涵盖使用以下Android测试的方法Mockito.

I know there are quite a few questions (and answers) for this topic, but I've tried everything I found in SO and other sites and I haven't found a way to make JaCoCo include coverage for Android tests that use Mockito.

我的问题: 我想使用JaCoCo生成单元测试和仪器测试(androidTest)的代码覆盖率.我正在使用Mockito模拟某些类.我在GitHub上找到了一个使用JaCoCo的示例,并将其用作起点.

My problem: I want to use JaCoCo to generate code coverage of both Unit Test and Instrumentation Test (androidTest). I'm using Mockito to mock some of the classes. I found a sample in GitHub to use JaCoCo and used it as a starting point.

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

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

When I run the custom jacocoTestReport task included in that example, the code coverage report is properly generated and code coverage is at 100%. The report includes both unit test and android test. However, that sample is not using Mockito (which I need), so I added the following to app/build.gradle

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

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

I added a very simple Java class called Util at app/src/main/java/net/rafaeltoledo/coverage/Util.java

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

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

And added the following simple test to the existing android test at app/src/androidTest/java/net/rafaeltoledo/coverage/MainActivityTest.java

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

当我再次运行jacocoTestReport时,代码覆盖率下降到88%,并且该报告实际上显示我的测试未覆盖Util类,即使我显然有一个行使该类的测试也是如此.

When I run the jacocoTestReport again, code coverage drops to 88% and the report in fact shows the Util class was not covered by my tests, even though I clearly have a test that exercises that class.

((我想添加报告的屏幕截图,但我的信誉不高,因此这里是

(I wanted to add screenshots of the reports but I don't have enough reputation, so here's a link to the coverage report and execution report that shows that both tests were in fact executed)

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

Versions info: Gradle plug-in: 2.3.3 Jacoco: 0.7.8.201612092310 Android Studio: 2.3.3 Android build tools: 25.0.2

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

Is this a Jacoco limitation or am I doing something wrong?

推荐答案

我做错什么了吗?

am I doing something wrong?

我们将Android放在一旁,因为IMO显然对您对核心内容的期望/理解有问题-嘲笑:

Let's put aside Android, because there is IMO clearly something wrong with your expectations/understanding about core thing here - mocking:

即使我显然有一个测试该课程的考试.

even though I clearly have a test that exercises that class.

通过

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

您不是在测试anIntMethod,而是在测试总是返回10的东西,无论实际写在anIntMethod中的是什么.

you are not testing anIntMethod, you are testing something that always returns 10, no matter what is actually written in anIntMethod.

覆盖率显示了已执行的内容,因此对于anIntMethod而言,由于未执行,因此绝对正确.

Coverage shows what was executed and hence absolutely correct that it is zero for anIntMethod since it is not executed.

模拟用于将受测类与它的依赖关系隔离开来,但不能替代它,否则就不会测试真实的代码.

Mocking is used to isolate class under test from its dependencies, but not to replace it, otherwise you're not testing real code.

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

Here is an example of proper usage of mocking:

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覆盖率后是

以及部分嘲讽的情况:

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());
  }
}

在两种情况下,模拟零件均显示为未覆盖,这是正确的.

In both cases mocked parts are shown as uncovered and this is correct.

这篇关于JaCoCo + Mockito + Android测试:零覆盖率报告的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆