为什么 Spring @Service 方法在 JaCoCo 中以 0% 的代码覆盖率出现?
Why Spring @Service methods appear with 0% code coverage in JaCoCo?
已加载这些库:
- JUnit 5.3.2
- JaCoCo 0.8.2
- Mockito 2.10.0
只有元素 "static {...}" 以 100% 的覆盖率出现。其余所有为 0%:
单元测试 class 有注释 @ExtendWith(SpringExtension.class)
和 @AutoConfigureMockMvc
。该服务注入 @Mock
.
doReturn(actual).when(service).get(param);
when(service.get(param)).thenReturn(actual);
expected = service.get(param);
verify(service, times(1)).get(param);
assertEquals(expected, actual);
assertEquals(actual, expected);
我的ServiceImpl
class点击任何方法都是红色的。它扩展了一个抽象class。 Jackson 的 ObjectMapper
是红色的,也是方法中的整行。例如:
public CustomReturnObject get(final CustomParamObject paramObject) {
try {
return retryTemplate.execute(status -> {
String json = repository.get(paramObject);
CustomReturnObject returnObject = json2CustomObject(json, paramObject);
if (returnObject == null) {
returnObject = new CustomReturnObject();
returnObject.setId(paramObject.getId());
}
return returnObject;
});
} catch (Exception ex) {
log.error(ex.getMessage(), ex);
return null;
}
}
与 类似,让我们把 Spring 搁置一旁,因为 IMO 显然有问题 expectations/understanding 关于这里的核心问题 - 嘲笑。
由
doReturn(actual).when(service).get(param);
expected = service.get(param);
verify(service, times(1)).get(param);
assertEquals(expected, actual);
你不是在测试 get
方法,你是在测试总是 returns actual
的东西,不管 get
中实际写的是什么,因为在这种情况下它没有被执行。
这里complete example作为证明:
src/main/java/hello/GreetingService.java
:
package hello;
class GreetingService {
Object get(Object param) {
throw new UnsupportedOperationException();
}
}
src/test/java/hello/GreetingServiceTest.java
:
package hello;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.verify;
@ExtendWith(MockitoExtension.class)
public class GreetingServiceTest {
@Mock
public GreetingService service;
@Test
void test() {
Object param = new Object();
Object actual = new Object();
doReturn(actual).when(service).get(param);
Object expected = service.get(param);
verify(service, Mockito.times(1)).get(param);
assertEquals(expected, actual);
}
}
build.gradle
:
apply plugin: 'java'
sourceCompatibility = 1.8
targetCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
testCompile 'org.mockito:mockito-junit-jupiter:2.23.4'
}
真正的方法get
抛出UnsupportedOperationException
,但是上面的测试成功了,所以真正的方法没有被执行。作为证明 get
未执行的另一种方法:将断点放入其中并在调试模式下从 IDE 执行测试 - 断点不会到达。
覆盖率显示了真正执行的内容,因此对于未执行的方法来说它是零是绝对正确的。
已加载这些库:
- JUnit 5.3.2
- JaCoCo 0.8.2
- Mockito 2.10.0
只有元素 "static {...}" 以 100% 的覆盖率出现。其余所有为 0%:
单元测试 class 有注释 @ExtendWith(SpringExtension.class)
和 @AutoConfigureMockMvc
。该服务注入 @Mock
.
doReturn(actual).when(service).get(param);
when(service.get(param)).thenReturn(actual);
expected = service.get(param);
verify(service, times(1)).get(param);
assertEquals(expected, actual);
assertEquals(actual, expected);
我的ServiceImpl
class点击任何方法都是红色的。它扩展了一个抽象class。 Jackson 的 ObjectMapper
是红色的,也是方法中的整行。例如:
public CustomReturnObject get(final CustomParamObject paramObject) {
try {
return retryTemplate.execute(status -> {
String json = repository.get(paramObject);
CustomReturnObject returnObject = json2CustomObject(json, paramObject);
if (returnObject == null) {
returnObject = new CustomReturnObject();
returnObject.setId(paramObject.getId());
}
return returnObject;
});
} catch (Exception ex) {
log.error(ex.getMessage(), ex);
return null;
}
}
与
由
doReturn(actual).when(service).get(param); expected = service.get(param); verify(service, times(1)).get(param); assertEquals(expected, actual);
你不是在测试 get
方法,你是在测试总是 returns actual
的东西,不管 get
中实际写的是什么,因为在这种情况下它没有被执行。
这里complete example作为证明:
src/main/java/hello/GreetingService.java
:
package hello;
class GreetingService {
Object get(Object param) {
throw new UnsupportedOperationException();
}
}
src/test/java/hello/GreetingServiceTest.java
:
package hello;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.verify;
@ExtendWith(MockitoExtension.class)
public class GreetingServiceTest {
@Mock
public GreetingService service;
@Test
void test() {
Object param = new Object();
Object actual = new Object();
doReturn(actual).when(service).get(param);
Object expected = service.get(param);
verify(service, Mockito.times(1)).get(param);
assertEquals(expected, actual);
}
}
build.gradle
:
apply plugin: 'java'
sourceCompatibility = 1.8
targetCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
testCompile 'org.mockito:mockito-junit-jupiter:2.23.4'
}
真正的方法get
抛出UnsupportedOperationException
,但是上面的测试成功了,所以真正的方法没有被执行。作为证明 get
未执行的另一种方法:将断点放入其中并在调试模式下从 IDE 执行测试 - 断点不会到达。
覆盖率显示了真正执行的内容,因此对于未执行的方法来说它是零是绝对正确的。