我有一些使用资源的 try 代码,在 jacoco 中它只覆盖了一半。所有的源代码行都是绿色的,但我得到一个黄色的小符号,告诉我只有 8 个分支中的 4 个被覆盖。
我无法弄清楚所有分支是什么,以及如何编写覆盖它们的代码。三个可能的地方抛出 PipelineException
。它们是 createStageList()
、processItem()
和隐含的 close()
- 不抛出任何异常,
- 从
createStageList()
抛出异常
- 从
processItem()
抛出异常
- 从
close()
抛出异常
- 从
processItem()
和close()
抛出异常
我想不出任何其他案例,但我仍然只涵盖了 8 个案例中的 4 个。
有人可以向我解释为什么它是 4 of 8 并且无论如何都要击中所有 8 个分支吗?我不擅长解密/阅读/解释字节码,但也许你是...... :) 我已经看过 https://github.com/jacoco/jacoco/issues/82 ,但它和它引用的问题都没有太大帮助(除了注意这是由于编译器生成的 block )
嗯,就在我写完这篇文章时,我想到了我上面提到的可能不会测试哪些情况......如果我做对了,我会发布一个答案。我确信这个问题及其答案无论如何都会对某人有所帮助。
编辑:不,我没找到。抛出 RuntimeExceptions(不由 catch block 处理)不再覆盖任何分支
最佳答案
好吧,我无法告诉您 Jacoco 的确切问题是什么,但我可以向您展示 Try With Resources 是如何编译的。基本上,有很多编译器生成的开关来处理不同点抛出的异常。
如果我们采用以下代码并编译它
public static void main(String[] args){
String a = "before";
try (CharArrayWriter br = new CharArrayWriter()) {
br.writeTo(null);
} catch (IOException e){
System.out.println(e.getMessage());
}
String a2 = "after";
}
然后反汇编,我们得到
.method static public main : ([Ljava/lang/String;)V
.limit stack 2
.limit locals 7
.catch java/lang/Throwable from L26 to L30 using L33
.catch java/lang/Throwable from L13 to L18 using L51
.catch [0] from L13 to L18 using L59
.catch java/lang/Throwable from L69 to L73 using L76
.catch [0] from L51 to L61 using L59
.catch java/io/IOException from L3 to L94 using L97
ldc 'before'
astore_1
L3:
new java/io/CharArrayWriter
dup
invokespecial java/io/CharArrayWriter <init> ()V
astore_2
aconst_null
astore_3
L13:
aload_2
aconst_null
invokevirtual java/io/CharArrayWriter writeTo (Ljava/io/Writer;)V
L18:
aload_2
ifnull L94
aload_3
ifnull L44
L26:
aload_2
invokevirtual java/io/CharArrayWriter close ()V
L30:
goto L94
L33:
.stack full
locals Object [Ljava/lang/String; Object java/lang/String Object java/io/CharArrayWriter Object java/lang/Throwable
stack Object java/lang/Throwable
.end stack
astore 4
aload_3
aload 4
invokevirtual java/lang/Throwable addSuppressed (Ljava/lang/Throwable;)V
goto L94
L44:
.stack same
aload_2
invokevirtual java/io/CharArrayWriter close ()V
goto L94
L51:
.stack same_locals_1_stack_item
stack Object java/lang/Throwable
.end stack
astore 4
aload 4
astore_3
aload 4
athrow
L59:
.stack same_locals_1_stack_item
stack Object java/lang/Throwable
.end stack
astore 5
L61:
aload_2
ifnull L91
aload_3
ifnull L87
L69:
aload_2
invokevirtual java/io/CharArrayWriter close ()V
L73:
goto L91
L76:
.stack full
locals Object [Ljava/lang/String; Object java/lang/String Object java/io/CharArrayWriter Object java/lang/Throwable Top Object java/lang/Throwable
stack Object java/lang/Throwable
.end stack
astore 6
aload_3
aload 6
invokevirtual java/lang/Throwable addSuppressed (Ljava/lang/Throwable;)V
goto L91
L87:
.stack same
aload_2
invokevirtual java/io/CharArrayWriter close ()V
L91:
.stack same
aload 5
athrow
L94:
.stack full
locals Object [Ljava/lang/String; Object java/lang/String
stack
.end stack
goto L108
L97:
.stack same_locals_1_stack_item
stack Object java/io/IOException
.end stack
astore_2
getstatic java/lang/System out Ljava/io/PrintStream;
aload_2
invokevirtual java/io/IOException getMessage ()Ljava/lang/String;
invokevirtual java/io/PrintStream println (Ljava/lang/String;)V
L108:
.stack same
ldc 'after'
astore_2
return
.end method
对于不会说字节码的人来说,这大致相当于下面的伪Java。我不得不使用 goto,因为字节码并不真正对应 Java 控制流。
如您所见,有很多情况可以处理被抑制异常的各种可能性。能够涵盖所有这些情况是不合理的。事实上,第一个 try block 上的 goto L59
分支是不可能到达的,因为第一个 catch Throwable 将捕获所有异常。
try{
CharArrayWriter br = new CharArrayWriter();
Throwable x = null;
try{
br.writeTo(null);
} catch (Throwable t) {goto L51;}
catch (Throwable t) {goto L59;}
if (br != null) {
if (x != null) {
try{
br.close();
} catch (Throwable t) {
x.addSuppressed(t);
}
} else {br.close();}
}
break;
try{
L51:
x = t;
throw t;
L59:
Throwable t2 = t;
} catch (Throwable t) {goto L59;}
if (br != null) {
if (x != null) {
try{
br.close();
} catch (Throwable t){
x.addSuppressed(t);
}
} else {br.close();}
}
throw t2;
} catch (IOException e) {
System.out.println(e)
}
关于java - 尝试资源的 8 个分支 - 可以进行 jacoco 覆盖吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17354150/