Lombok 由于其使用的便利性, 目前流傳非常廣泛。甚至有呼聲希望其能被Java官方引入,成為JDK的一部分。
當然凡事都有兩面性,Lombok的引入也是有代價的。一時注釋一時爽,結(jié)果導(dǎo)致代碼在不知不覺中翻了好幾倍。
例如以下幾個簡單的注解,背后是N多個自動生成的方法:
- @Data注解:這是若干個注解的組合,包括有@Setter、@Getter、@ToString和@EqualsAndHashCode的功能,還會添加一個公共的構(gòu)造方法。staticConstructor 參數(shù)可將構(gòu)造方法置為private,并提供一個獲取對象的靜態(tài)方法。
- @Builder:使用私有構(gòu)造函數(shù)生成一個名為TBuilder的內(nèi)部類,創(chuàng)建一個構(gòu)造器。
- @NoArgsConstructor:該注解使用在類上,該注解提供一個無參構(gòu)造
- @AllArgsConstructor:該注解使用在類上,該注解提供一個全參數(shù)的構(gòu)造方法,默認不提供無參構(gòu)造方法。
這其中尤其是@Data這個注解,會附帶相當多的方法。
默認情況下,由于Jacoco不會區(qū)分Lombok生成的代碼和正常的源代碼。結(jié)果,在引入Lombok后就會發(fā)現(xiàn),覆蓋率通常會低得讓人匪夷所思。例如某個項目,通過Jacoco獲取到的代碼行數(shù)以及覆蓋率為:
可見,這個覆蓋率是非常低的,會被質(zhì)量門禁判違規(guī)(常見會要求>50%甚至>80%)。
這種情況下,開發(fā)者一般會有兩個選擇:
- 專門為這些生成的代碼編寫單元測試用例
- 要求降低質(zhì)量門禁中的覆蓋率要求
通常這兩個方案都是不可取的。
專門為這些生成的代碼編寫用例是沒有意義的。既然使用了Lombok,一個默認的前提就是Lombok是正確可靠的,為這些自動生成的代碼進行單元測試不是一件高優(yōu)先級的事情,還是放過已經(jīng)996的碼農(nóng)和他們的頭發(fā)吧,要愛護那些愿意寫單元測試的好同志。
第二種方案也不可取,這會引入一個非常不好的開始,因為破窗效應(yīng),馬上質(zhì)量門禁也沒有意義了。千萬個教訓(xùn)告訴我們,千萬不要去考驗人性。
兩種選擇都沒有意義,也都不可取,于是馬上就有人想到了第三種方法。
3 手工排除Bean
無論是Jacoco還是Sonar,都提供了exclude的方式,通過配置項來指定統(tǒng)計時排除某些特定的包或者類。如對于Jacoco可以在jacoco-maven-plugin的<configuration>中有如下配置,用于排除指定的內(nèi)容。
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.7</version>
<configuration>
<excludes>
<exclude>**/*DTO.*</exclude>
<exclude>**/domain/**/*</exclude>
</excludes>
</excludes>
</configuration>
<executions>
<execution>
<id>default-prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>default-report</id>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
第一個<exclude>標簽將吧所有DTO結(jié)尾的類排除,而第二個<exclude>標簽將把domain目錄和子目錄下的所有類都排除出去。
通過這個方式,也可以在數(shù)據(jù)源頭上進行排除。
類似的,還可以通過基于jacoco覆蓋率報告來自研解析工具,進行覆蓋率或者增量覆蓋率計算。這個過程中,也可以指定需要排除的包或者類,實現(xiàn)類似的做法。
當然,這種方式也需要項目有一些項目結(jié)構(gòu)和命名上的約定,以保證過濾的正確。另外,既然放開了過濾的條件,有可能會讓人鉆空子。
4 使用Sonarqube 而不是Jacoco的結(jié)果
雖然Jacoco中的數(shù)據(jù)受到了lombok的污染,但是SonarQube由于有自身代碼行的計算是根據(jù)掃描的源碼,再根據(jù)自身的算法進行計算,并不是根據(jù)Jacoco提供的數(shù)據(jù)。再由此計算覆蓋率的時候,就可以部分規(guī)避掉這個問題了。所以這是一個正解。當然,由于SonarQube和Jacoco的代碼行、覆蓋率等算法有差異,最好是保持指標數(shù)據(jù)源前后的一致性,避免混用。
5 使用lombok.addLombokGeneratedAnnotation
其實從Jacoco 0.8.0開始,其實就具備了可以將lobmok生成的代碼從Jacoco報告中排除的能力。發(fā)布說明可以參見
https://github.com/jacoco/jacoco/pull/513
具體做法是,在項目的根目錄下新建一個名字為lombok.config的文件,里面有如下的內(nèi)容,
config.stopBubbling = true
lombok.addLombokGeneratedAnnotation = true
Lombok在為由其生成的構(gòu)造方法、方法、字段和類型中增加@Generated注解,然后Jacoco借助這個注解來實現(xiàn)更為準去的排除。排除以后的結(jié)果如下,
當然,這個方案對兩者的版本也有限制,要求Lombok >= 1.16.14, jacoco>0.8.0
總結(jié)一下,面對lombok,有如下五種解決方案,推薦后兩種哦。
1專門為這些生成的代碼編寫單元測試用例 【X】
2要求降低質(zhì)量門禁中的覆蓋率要求【X】
3手工排除Bean 【X】
4使用Sonarqube 而不是Jacoco的結(jié)果【OK】文章來源:http://www.zghlxwxcb.cn/news/detail-471576.html
5使用lombok.addLombokGeneratedAnnotation 【OK】文章來源地址http://www.zghlxwxcb.cn/news/detail-471576.html
到了這里,關(guān)于Lombok導(dǎo)致代碼單元測試覆蓋率崩塌的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!