Gradle自定义UnitTestTask获取外部配置属性始终为null问题
问题根源
你遇到的问题是配置阶段执行顺序导致的:
- 在插件中注册
UnitTestTask时,属于Gradle配置阶段的早期逻辑,此时用户通过tasks.withType<UnitTestTask>设置variantsToExclude的代码还未执行,直接取variantsToExclude.orNull必然是null。 - 同时你直接计算
unitTestTasks并设置finalizedBy属于即时计算,后续variantsToExclude被赋值后,任务集合也不会更新。
解决方案:用Gradle懒加载API延迟任务集合计算
Gradle提供了Provider API实现懒加载,让任务集合的计算延迟到真正需要的时候(比如任务执行前、依赖解析时),此时variantsToExclude已经被用户配置赋值。
修改插件中的Task注册代码如下:
override fun apply(project: Project) { // 假设已定义以下常量 val UNIT_TEST_TASK_NAME = "unitTestTask" val KOVER_REPORT_TASK_NAME = "koverXmlReport" project.tasks.register<UnitTestTask>(UNIT_TEST_TASK_NAME) { task -> // 用provider包装任务筛选逻辑,延迟执行 val unitTestTasksProvider = project.provider { val variants = task.variantsToExclude.orNull project.allprojects.flatMap { subProject -> subProject.tasks.matching { subTask -> if (variants?.isNotEmpty() == true) { // Kotlin字符串中转义字符需双反斜杠,修正原正则的\b为\\b subTask.name.matches("\\b(koverXmlReport\\w+)\\b".toRegex()) && variants.none { variant -> subTask.name.contains(variant) } } else { subTask.name == KOVER_REPORT_TASK_NAME } } } } // 将懒加载的Provider传给finalizedBy,Gradle自动处理依赖 finalizedBy(unitTestTasksProvider) // 打印逻辑移到任务执行前的doFirst阶段,确保拿到正确结果 task.doFirst { val tasksToExecute = unitTestTasksProvider.get() println("tasks to execute: $tasksToExecute") } } }
关键修改点说明
- 用
project.provider包装逻辑:
内部代码不会立即执行,只会在Gradle需要确定任务依赖或任务即将执行时运行,此时用户的variantsToExclude配置已生效。 - 修正正则转义问题:
原代码中的"\b"会被解析为退格字符,必须改为"\\b"才能正确匹配单词边界。 - 打印逻辑移至
doFirst:
原println在配置阶段执行,无法拿到正确任务集合,移到doFirst可在任务执行前输出正确结果。
额外注意事项
确保用户的配置代码(tasks.withType<UnitTestTask>)在插件应用之后执行,通常用户的build.gradle.kts会先声明plugins { id("你的插件ID") }再配置任务,这个顺序无需调整。
内容的提问来源于stack exchange,提问作者Itoun
相关产品推荐
相关产品推荐

