单元测试之关于JaCoCo和PowerMock冲突导致类覆盖率为0的问题
在使用Mockito和PowerMock寫單測的時候發現,如果使用了PowerMock的@PrepareForTest注解,JaCoCo在統計代碼覆蓋率的時候就會忽略注解@PrepareForTest({})里面的類,導致覆蓋率統計不準確
對于一些工具類,我們可以先使用@PrepareForTest完成單測的開發,再單獨對工具類寫單測就行了,只要@PrepareForTest里面的類不是自己的項目代碼就可以了(比方說第三方jar包提供的), 但是在遇到系統類的時候就不行了。因為PowerMock 在mock系統類的返回結果時,就需要在@PrepareForTest{()}里寫上調用系統類的Class,這樣對應的業務類就無法被統計到
這是由于@PrepareForTest和java 覆蓋率工具(Java Code Coverage – JaCoCo)沖突導致的
這是官方的解釋:
Code coverage with JaCoCo
The simplest way to use JaCoCo it is — on-the-fly instrumentation with using JaCoCo Java Agent. In this case a class in modified when it is being loaded. You can just run you application with JaCoCo agent and a code coverage is calculated. This way is used by Eclemma and Intellij Idea. But there is a big issue. PowerMock instruments classes also. Javassist is used to modify classes. The main issue is that Javassist reads classes from disk and all JaCoCo changes are disappeared. As result zero code coverage for classes witch are loaded by PowerMock class loader.
JaCoCo和PowerMock都是通過在加載類的時候修改字節碼文件來實現統計覆蓋率和mock靜態類的功能。JaCoCo在加載class的時候會把統計代碼插入到class中,而PowerMock當使用了@PrepareForTest注解,在加載相關類的時候會從class文件重新讀取字節碼信息,導致JaCoCo的修改都沒有了,所以就沒辦法統計到了
為了解決上述問題,Github上也給出了一個解決方案,那就是使用JaCoCo的offline模式
<!--- 定義 jacoco 版本 --> <properties><jacoco.version>0.8.5</jacoco.version> </properties> <!--- 定義 jacoco 執行 offline 模式 goals --> <build><plugins><!-- 注意不是在pluginManagement, pluginManagement中只是聲明 --><plugin><groupId>org.jacoco</groupId><artifactId>jacoco-maven-plugin</artifactId><version>${jacoco.version}</version><executions><execution><id>default-instrument</id><goals><goal>instrument</goal></goals></execution><execution><id>default-restore-instrumented-classes</id><goals><goal>restore-instrumented-classes</goal></goals></execution></executions></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><!--離線模式必需指定, 否則到模塊根目錄而不是target目錄了--><configuration><systemPropertyVariables><jacoco-agent.destfile>target/jacoco.exec</jacoco-agent.destfile></systemPropertyVariables></configuration></plugin></plugins> </build> <!--- 定義 jacoco 依賴 注意不是在dependencyManagement, dependencyManagement中只是聲明--> <dependencies><dependency><groupId>org.jacoco</groupId><artifactId>org.jacoco.agent</artifactId><version>${jacoco.version}</version><classifier>runtime</classifier></dependency> </dependencies>這樣哪怕使用了@PrepareForTest注解,也不會影響到JaCoCo的代碼覆蓋率統計了,不過需要注意的是
Offline模式單元測試不能跨模塊, 不能源碼在A模塊單測寫在B模塊
比方說:項目分成了四個模塊,service,utils,dao,controller,你在寫service單測的時候哪怕調用了utils的代碼,但是在實際統計覆蓋率的時候是沒辦法統計到的,需要單獨針對每一個模塊寫單測
總結
以上是生活随笔為你收集整理的单元测试之关于JaCoCo和PowerMock冲突导致类覆盖率为0的问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 注意System.currentTime
- 下一篇: Java8 日期/时间(Date Tim