如何用Konsist禁止Kotlin项目中直接调用LocalDate.now()和Instant.now(),强制使用自定义DateTimeProvider?
如何用Konsist禁止Kotlin项目中直接调用LocalDate.now()和Instant.now(),强制使用自定义DateTimeProvider?
嘿,这个需求超实用,用Konsist完全能搞定!我给你一步步拆解实现方法:
首先,确保项目里已经引入Konsist依赖(可以用最新版本),比如在Gradle的build.gradle.kts中添加:
testImplementation("com.lemonappdev:konsist:0.15.0") testImplementation(kotlin("test"))
接下来,创建一个Konsist测试类,比如DateTimeProviderUsageTest,在里面编写规则检查代码:
import com.lemonappdev.konsist.api.Konsist import com.lemonappdev.konsist.api.ext.list.withNameNot import com.lemonappdev.konsist.api.verify.assertFalse import org.junit.jupiter.api.Test class DateTimeProviderUsageTest { @Test fun `no class except DateTimeProvider should call LocalDate now or Instant now directly`() { Konsist // 扫描整个项目的代码范围 .scopeFromProject() // 筛选出所有类文件 .classes() // 排除自定义的DateTimeProvider类(允许它调用原生now方法) .withNameNot("DateTimeProvider") // 断言所有剩余类都不满足违规条件 .assertFalse( message = "请勿直接调用LocalDate.now()或Instant.now(),请使用自定义的DateTimeProvider!" ) { klass -> // 检查类内是否存在直接调用目标方法的代码 klass.hasFunctionCall { call -> (call.name == "now" && call.containingClassName == "java.time.LocalDate") || (call.name == "now" && call.containingClassName == "java.time.Instant") } } } }
代码细节解释:
scopeFromProject():默认扫描整个项目代码,你也可以用scopeFromPackage("com.yourproject")指定特定包缩小范围withNameNot("DateTimeProvider"):精准排除我们的自定义时间提供者类,避免误判assertFalse:核心断言逻辑,只要有类触发了违规条件,测试就会失败并抛出自定义提示hasFunctionCall:检查类内部的函数调用,这里精准匹配LocalDate.now()和Instant.now()的调用
优化小技巧:
如果你的DateTimeProvider在特定包下(比如com.yourproject.utils),可以用更精准的方式排除,避免重名类干扰:
// 先定位到指定包下的DateTimeProvider val dateTimeProvider = Konsist .scopeFromPackage("com.yourproject.utils") .classes() .withName("DateTimeProvider") // 再扫描整个项目并排除这个类 Konsist .scopeFromProject() .classes() .exclude(dateTimeProvider) .assertFalse(...) { ... }
最后运行这个JUnit测试就好啦!只要项目里有类直接调用了LocalDate.now()或Instant.now(),测试就会报错,明确指出违规的类,帮你强制推行DateTimeProvider的规范使用。
备注:内容来源于stack exchange,提问作者Martin
相关产品推荐
相关产品推荐

