JaCoCo + Mockito + Android 测试:零覆盖率报告
JaCoCo + Mockito + Android tests: Zero coverage reported
我知道这个主题有很多问题(和答案),但我已经尝试了我在 SO 和其他网站上找到的所有内容,但我还没有找到让 JaCoCo 包含 Android 使用 Mockito 的测试。
我的问题:
我想使用 JaCoCo 生成单元测试和仪器测试 (androidTest) 的代码覆盖率。我正在使用 Mockito 模拟一些 classes。我在 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 class 名为 Util。java
public class Util {
public int anIntMethod() {
return 0;
}
}
并在 app/src/androidTest/java/net/rafaeltoledo/coverage/MainActivityTest 的现有 android 测试中添加了以下简单测试。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 class 没有被我的测试覆盖,尽管我显然有一个测试class 的练习。
(我想添加报告的屏幕截图,但我没有足够的声誉,所以这里有一个 link 到 coverage report and execution report,表明这两个测试实际上都已执行)
版本信息:
Gradle插件:2.3.3
雅可可:0.7.8.201612092310
Android 工作室:2.3.3
Android 构建工具:25.0.2
这是 Jacoco 的限制还是我做错了什么?
am I doing something wrong?
让我们搁置一旁 Android,因为 IMO 显然有问题 expectations/understanding 关于这里的核心内容 - 嘲笑:
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
,你是在测试总是 returns 10
的东西,不管 anIntMethod
.
中实际写的是什么
覆盖率显示了执行的内容,因此绝对正确的是 anIntMethod
是零,因为它没有被执行。
Mocking 用于将测试下的class与其依赖项隔离开来,而不是替换它,否则你不是在测试真正的代码。
下面是正确使用模拟的示例:
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());
}
}
在这两种情况下,模拟部分都显示为未覆盖,这是正确的。
我知道这个主题有很多问题(和答案),但我已经尝试了我在 SO 和其他网站上找到的所有内容,但我还没有找到让 JaCoCo 包含 Android 使用 Mockito 的测试。
我的问题: 我想使用 JaCoCo 生成单元测试和仪器测试 (androidTest) 的代码覆盖率。我正在使用 Mockito 模拟一些 classes。我在 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 class 名为 Util。java
public class Util {
public int anIntMethod() {
return 0;
}
}
并在 app/src/androidTest/java/net/rafaeltoledo/coverage/MainActivityTest 的现有 android 测试中添加了以下简单测试。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 class 没有被我的测试覆盖,尽管我显然有一个测试class 的练习。
(我想添加报告的屏幕截图,但我没有足够的声誉,所以这里有一个 link 到 coverage report and execution report,表明这两个测试实际上都已执行)
版本信息: Gradle插件:2.3.3 雅可可:0.7.8.201612092310 Android 工作室:2.3.3 Android 构建工具:25.0.2
这是 Jacoco 的限制还是我做错了什么?
am I doing something wrong?
让我们搁置一旁 Android,因为 IMO 显然有问题 expectations/understanding 关于这里的核心内容 - 嘲笑:
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
,你是在测试总是 returns 10
的东西,不管 anIntMethod
.
覆盖率显示了执行的内容,因此绝对正确的是 anIntMethod
是零,因为它没有被执行。
Mocking 用于将测试下的class与其依赖项隔离开来,而不是替换它,否则你不是在测试真正的代码。
下面是正确使用模拟的示例:
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());
}
}
在这两种情况下,模拟部分都显示为未覆盖,这是正确的。