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

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

问题描述

我知道这个主题有很多问题(和答案),但我已经尝试了我在 SO 和其他网站上找到的所有内容,但我还没有找到一种方法让 JaCoCo 包含使用的 Android 测试的覆盖范围莫基托.

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

以及部分模拟的情况:

src/main/java/Util.java:

公共类 Util {整数获取(){返回0;}int anIntMethod() {返回获取();}}

src/test/java/UtilTest.java:

import org.junit.Test;导入 org.mockito.Mockito;导入静态 org.junit.Assert.assertEquals;公共类 UtilTest {@测试公共无效 utilMethod() {Util util = Mockito.mock(实用程序类,Mockito.withSettings().defaultAnswer(Mockito.CALLS_REAL_METHODS));Mockito.doReturn(10).when(util).get();assertEquals(10, util.anIntMethod());}}

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

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.

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

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'
}

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

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

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)

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

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

解决方案

am I doing something wrong?

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.

By

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

you are not testing anIntMethod, you are testing something that always returns 10, no matter what is actually written in 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"
}

And after execution of gradle build jacocoTestReport coverage is

And case of partial mocking:

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 测试:报告的零覆盖率的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

Android release APK crash with java.lang.AssertionError: impossible in java.lang.Enum(Android 发布 APK 因 java.lang.AssertionError 崩溃:在 java.lang.Enum 中不可能)
Finished with Non Zero Exit Value 3(以非零退出值 3 结束)
On gradle:3.0.0 More than one file was found with OS independent path #39;META-INF/ASL2.0#39;(在 gradle:3.0.0 上找到多个文件,其独立于操作系统的路径为“META-INF/ASL2.0)
Android : app loading library at runtime on Lollipop but not IceCreamSandwich(Android:运行时在 Lollipop 上而不是 IceCreamSandwich 上的应用程序加载库)
buildConfigField depending on flavor + buildType(buildConfigField 取决于风味 + buildType)
How do I suppress warnings when compiling an android library with gradle?(使用 gradle 编译 android 库时如何抑制警告?)