alibaba / testable-mock

换种思路写Mock,让单元测试更简单
https://alibaba.github.io/testable-mock/
MIT License
1.82k stars 309 forks source link

Gradle jacoco 覆盖率为0 #245

Open ermaic opened 2 years ago

ermaic commented 2 years ago

gradle 6.8.3, testable-mock 0.7.0 test case能跑成功,但在跑gradle jacoco plugin的jacocoTestReport task,有如下显示: [ant:jacocoReport] Class in bundle '项目名' do not match with execution data. For report generation the same class files must be used as at runtime. 结果是coverage report里的覆盖率都为0 请问如何解决?是否有gradle+jacoco+testable-mock的例子可供参考?

linfan commented 2 years ago

gradle + jacoco 的暂时没有现成的例子...

ttbadr commented 2 years ago

@ermaic 有可能是jacoco agent放在testable agent后面了, 把testable agent放在jacoco agent后面试一下

luoleijun commented 2 years ago

gradle+jacoco+testable-mock的例子,我写了个demo,见:https://github.com/luoleijun/testablemock-demo 写这个demo参考了这个文档: https://www.jacoco.org/jacoco/trunk/doc/cli.html
https://www.jacoco.org/jacoco/trunk/doc/index.html

但上面这个例子有个新问题,排除类无效,大佬们有没有解法?下面是排除类写法

test { group "verification" jvmArgs "-javaagent:${classpath.find { it.name.contains("jacoco.agent") }.absolutePath}=destfile=build/jacoco/test.exec,append=true," + "excludes=com/luo/std/**," + "inclnolocationclasses=false,dumponexit=true,output=file,jmx=false", "-javaagent:${classpath.find { it.name.contains("testable-agent") }.absolutePath}" useJUnitPlatform() }

CapriWits commented 1 year ago

遇到相同问题,Jacoco 测试覆盖率为 0,求 Gradle + Jacoco + TestableMock 的配置方式:)

luoleijun commented 1 year ago

放弃testablemock吧,这个问题解决了还会有新的问题,阿里支持力度不够。用Mockito吧  

luo @.***

 

------------------ Original ------------------ From: @.***>; Date: 2022年11月25日(星期五) 下午5:30 To: "alibaba/testable-mock"; Cc: "Comment"; Subject: Re: [alibaba/testable-mock] Gradle jacoco 覆盖率为0 (Issue #245)

遇到相同问题,Jacoco 测试覆盖率为 0,求 Gradle + Jacoco + TestableMock 的配置方式:)

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.Message ID: @.***>

CapriWits commented 1 year ago

有其他的解决方案吗,还有哪些框架可以支持 mock private, final, static 方法,Mockito-inline 可以 mock static 方法,但是对于 private, final 方法就束手无策了,目前用的 SpringBoot 版本比较高,JUnit5 不支持 PowerMockito,所以陷入僵局,好不容易发现 TestableMock,结果发现跑 Jacoco 覆盖率是 0

linfan commented 1 year ago

Gradle我们用得比较少,所以确实没有太多经验。

可以确定的是,在Maven下Testable和Jacoco可以正常共存,且使用Testable不会影响Jacoco覆盖率,原理上来说Gradle应该能达到相同效果。

CapriWits commented 1 year ago

感谢您的回复。按照 Java Demo 的 gradle 配置,在 IDEA Coverage Test by Jacoco 会报错,Gradle jacocoTestReport 生成的 coverage 报告中也是命中率为 0,推测是 Javaagent 没有生效,应该是 Jacoco 字节码插桩与 TestableMock 字节码修改相冲突。在 Gradle 环境下暂无解决方案 : (

linfan commented 1 year ago

从原理来讲,两者的字节码修改本身互不影响。

其实问题的原因我大致知道,是因为文档里的配置方法直接覆写了jvmArgs参数的值,会导致Jacoco Gradle插件注入的启动参数被替换掉,使得Jacoco插桩没有被执行(因为Jacoco的原理也是字节码注入,所以同样需要修改jvmArgs参数,只是它把这个过程封装到自己的Gradle插件里面了)。

在Maven的pom.xml里是使用@{argLine}占位符来引用原始的JVM参数内容,从而确保Testable的参数是被追加而不是覆写原有参数(如果直接覆写同样会导致Jacoco覆盖率跌零,因为没有插桩)。但我不太清楚在Gradle里如何表达参数追加。

@luoleijun 前面已经给了一个思路,是在设置jvmArgs参数的时候加上 "-javaagent:${classpath.find { it.name.contains("jacoco.agent") }.absolutePath}" 这部分,来显示加载Jacoco的JavaAgent,但他也提到通过这样方式的Jacoco配置项(比如排除类)无法生效,所以并不是一个完美方案。

另一种可能的解决办法是给Testable也制作一个Gradle插件,正如我们已经提供了Testable Maven插件那样,在插件里实现参数追加会相对容易一些。这件事暂时不在我们的计划内,但如果有开发者愿意贡献相关Gradle插件的PR,我们会非常乐意接纳 : D