
使用 Camunda DMN JUnit 5 扩展在测试中注入 DMN 引擎依赖配置、注入方式与自定义引擎配置实战【免费下载链接】camunda-bpm-platformCamunda 7 CE is End of Life (EoL). Please check out Camunda 8 instead (https://github.com/camunda/camunda) or read about Camunda 7 Enterprise End of Life (https://camunda.com/blog/2025/02/camunda-7-enterprise-end-of-life-extension/) – Camunda 7 CE was a flexible framework for workflow and decision automation using BPMN and DMN.项目地址: https://gitcode.com/GitHub_Trending/ca/camunda-bpm-platform输出文章Camunda Platform DMN JUnit 5 扩展实战在测试中注入 DMN 引擎的完整指南本指南围绕 test-utils/junit5-extension-dmn/README.md 展开系统讲解如何通过camunda-dmn-junit5这个 JUnit 5 扩展在测试类中快速获得一个可用的DmnEngine实例。文章覆盖 Maven 依赖引入、ExtendWith字段注入与方法参数注入两种使用姿势并结合仓库源码剖析扩展的实现原理最后介绍通过RegisterExtensionforConfiguration使用自定义DmnEngineConfiguration的高级用法。读完本文你可以在不依赖流程引擎、不编写样板代码的情况下直接对 DMN 决策模型编写单元测试。1. 扩展是什么一句话定位camunda-dmn-junit5是 Camunda Platform 提供的一个轻量级 JUnit 5 扩展Extension核心能力只有一件事在 JUnit 5 测试中创建一个DmnEngine并注入到测试类字段或测试方法参数中。它与面向流程引擎的 camunda-bpm-junit5 定位互补——前者注入ProcessEngine后者专门服务于DmnEngine两者都可与camunda-engine-dmnengine-dmn/engine配合使用。该扩展的实现只有一个类 DmnEngineExtension.java同时实现了 JUnit 5 的TestInstancePostProcessor、BeforeTestExecutionCallback与ParameterResolver三个扩展接口从而同时支持字段注入和参数注入两条路径。2. 快速上手2.1 添加 Maven 依赖在pom.xml中加入如下依赖dependency groupIdorg.camunda.bpm.dmn/groupId artifactIdcamunda-dmn-junit5/artifactId version7.20.0/version scopetest/scope /dependency要点说明scopetest/scope是必须的该扩展只在测试编译与运行期使用不应被打进生产制品。版本号请按你使用的 Camunda 发行版对齐。当前仓库对应版本为 7.24.0-SNAPSHOT见 pom.xml 中的 parent 版本README 示例中的7.20.0是可用的社区版坐标之一。扩展对camunda-engine-dmn与 JUnit Jupiter 均以provided作用域声明见 pom.xml这意味着你的测试工程需要自行引入camunda-engine-dmn获得DmnEngine类型和 JUnit 5获得ExtendWith等注解工程自身则使用junit-bom统一管理 JUnit 5 版本5.9.3见 pom.xml。如果仅想测试 DMN 引擎本身可以直接引入 engine-dmn/engine 模块org.camunda.bpm.dmn:camunda-engine-dmn它自带DmnEngine、DmnEngineConfiguration与测试用 DmnEngineRule。2.2 编写第一个测试ExtendWith 字段注入import org.camunda.bpm.dmn.engine.DmnEngine; import org.junit.jupiter.api.extension.ExtendWith; ExtendWith(DmnEngineExtension.class) class MyDmnTest { // 声明一个字段扩展会自动注入 DmnEngine 实例 public DmnEngine dmnEngine; Test void shouldEvaluateDecision() { // 直接使用注入的 dmnEngine 解析并求值决策 } }2.3 方法参数注入按需获取如果不想声明字段也可以把它作为测试方法参数扩展会按类型匹配自动注入Test void testDecision(DmnEngine dmnEngine) { // 使用 dmnEngine }字段注入与参数注入可以混用选择哪种取决于代码风格仓库自带的测试 DmnEngineExtensionTest.java 就同时演示了两种方式shouldInjectClassField用字段、shouldInjectMethodParameter用参数并且两个测试共用同一个注入实例完成相同的决策求值断言。3. 一个可以跑通的完整示例参考 DmnEngineExtensionTest.java 与仓库内的 DMN 样例文件 DecisionWithLiteralExpression.dmn一个完整可运行的测试如下package org.camunda.bpm.dmn.engine.test.junit5; import static org.assertj.core.api.Assertions.assertThat; import static org.camunda.bpm.engine.variable.Variables.createVariables; import org.camunda.bpm.dmn.engine.DmnDecisionResult; import org.camunda.bpm.dmn.engine.DmnEngine; import org.camunda.commons.utils.IoUtil; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; ExtendWith(DmnEngineExtension.class) class DmnEngineExtensionTest { public static final String DMN_MINIMAL org/camunda/bpm/dmn/engine/test/junit5/DecisionWithLiteralExpression.dmn; // 字段注入 DmnEngine dmnEngineField; Test void shouldInjectClassField() { shouldEvaluateDecisionWithLiteralExpression(dmnEngineField); } // 方法参数注入 Test void shouldInjectMethodParameter(DmnEngine dmnEngineParam) { shouldEvaluateDecisionWithLiteralExpression(dmnEngineParam); } protected void shouldEvaluateDecisionWithLiteralExpression(DmnEngine dmnEngine) { DmnDecisionResult result dmnEngine.evaluateDecision( dmnEngine.parseDecision(decision, IoUtil.fileAsStream(DMN_MINIMAL)), createVariables() .putValue(a, 2) .putValue(b, 3)); assertThat(result.getSingleResult()).containsOnlyKeys(c); assertThat((int) result.getSingleEntry()).isEqualTo(5); } }对应 DMN 决策模型位于 engine-dmn/engine/src/test/resources/org/camunda/bpm/dmn/engine/api/DecisionWithLiteralExpression.dmn?xml version1.0 encodingUTF-8? definitions xmlnshttp://www.omg.org/spec/DMN/20151101/dmn.xsd iddefinitions nameDefinitions namespacehttp://camunda.org/schema/1.0/dmn decision iddecision nameDecision with Literal Expression variable nameresult typeRefstring / literalExpression textinput ok ? ok : notok/text /literalExpression /decision /definitions这个示例展示了使用注入的DmnEngine的典型三步流程parseDecision(decision, stream)按决策id解析 DMN 模型得到DmnDecisionDmnEngine接口定义见 DmnEngine.javacreateVariables().putValue(...)通过 typed-values 模块的Variables工厂构建求值变量evaluateDecision(...)执行求值并返回DmnDecisionResult随后用 AssertJ 对结果做断言。4. 注入机制原理源码级解读DmnEngineExtension的类声明如下DmnEngineExtension.javapublic class DmnEngineExtension implements TestInstancePostProcessor, BeforeTestExecutionCallback, ParameterResolver {三条注入路径分别对应三个接口回调字段注入实例字段postProcessTestInstance在测试实例创建后被调用通过反射扫描测试类中类型为DmnEngine的字段并赋值injectIntoTestInstance使用getDeclaredFields()遍历即使字段是private也能注入因为injectDmnEngine会调用field.setAccessible(true)。字段注入static 字段beforeTestExecution在每个测试方法执行前再次执行同样的字段注入逻辑因此即使DmnEngine字段是static的也能在测试执行前被正确赋值——这由ExtensionContext.getTestInstance()拿到实例后注入实现。参数注入supportsParameter仅当参数类型严格等于DmnEngine.class时返回trueresolveParameter在类型匹配时初始化引擎并返回该实例。注意它是精确类型匹配子类或接口类型不会被注入。引擎创建采取惰性初始化initializeDmnEngine()只有在dmnEngine null时才调用dmnEngineConfiguration.buildEngine()构建因此同一个扩展实例在同一测试生命周期内复用一个引擎实例不会为每个测试方法重复创建。注入的类型判断可见 DmnEngineExtension.java参数解析与 DmnEngineExtension.java字段注入。5. 高级用法使用自定义 DMN 引擎配置默认情况下扩展使用DmnEngineConfiguration.createDefaultDmnEngineConfiguration()创建默认配置DmnEngineConfiguration.java。当测试需要自定义配置例如注册自定义表达式语言、自定义DmnDecisionEvaluationListener、设置引擎指标收集器等时可以使用静态工厂方法forConfiguration配合RegisterExtensionimport org.camunda.bpm.dmn.engine.DmnEngineConfiguration; import org.camunda.bpm.dmn.engine.impl.DefaultDmnEngineConfiguration; import org.junit.jupiter.api.extension.RegisterExtension; class RegisterDmnEngineExtensionTest { private DmnEngineConfiguration customConfiguration new DefaultDmnEngineConfiguration(); RegisterExtension private DmnEngineExtension dmnEngineExtension DmnEngineExtension.forConfiguration(customConfiguration); // 之后被注入的 DmnEngine 将基于 customConfiguration 构建 }forConfiguration的实现DmnEngineExtension.java对空配置做了防御public static DmnEngineExtension forConfiguration(DmnEngineConfiguration configuration) { return new DmnEngineExtension( Objects.requireNonNull(configuration, configuration must not be null)); }对应测试 RegisterDmnEngineExtensionTest.java 验证了三点行为传入null配置会抛出带信息configuration must not be null的NullPointerException注入到static字段、实例字段以及方法参数中的引擎其getConfiguration()都与传入的自定义配置对象相同assertThat(...getConfiguration()).isEqualTo(customConfiguration)三种注入方式static 字段、实例字段、方法参数行为一致。需要注意DmnEngineConfiguration的 Javadoc 明确指出对配置实例的修改也会影响已由该配置构建的引擎见 DmnEngineConfiguration.java因此在测试中复用配置对象时要注意状态共享。此外DmnEngineConfiguration还提供了丰富的可配置项例如引擎指标收集器setEngineMetricCollector、决策表求值监听器customPreDecisionTableEvaluationListeners等见 DmnEngineConfiguration.java这些都可以在测试中按需装配。6. 与 DmnEngineRuleJUnit 4的对比如果你的项目仍在使用 JUnit 4仓库同样提供了基于 Rule 的等效方案 DmnEngineRule.java。它与DmnEngineExtension的对应关系非常直接DmnEngineRule也支持默认配置构造时调用createDefaultDmnEngineConfiguration()与自定义配置两种构造方式并在内部通过dmnEngineConfiguration.buildEngine()构建引擎见 DmnEngineRule.java。从源码结构看两个类共享同一套引擎构建与配置注入思路只是接入点从 JUnit 4 的TestRule换成了 JUnit 5 的ExtensionAPI。对于新项目推荐直接使用camunda-dmn-junit5。7. 版本与维护说明依据 pom.xml 中模块描述7.24.0 是发布到 Maven Central 的最后一个社区版该库后续不再发布新版本。Camunda 7 社区版已进入 End of LifeEoL阶段项目 READMEREADME.md也明确提示用户转向 Camunda 8。因此本文介绍的能力基于当前仓库源码7.24.0-SNAPSHOT 时代验证在迁移到 Camunda 8 时请以新平台的测试工具为准。8. 小结使用方式关键代码适用场景默认引擎 字段注入ExtendWith(DmnEngineExtension.class)public DmnEngine dmnEngine;大多数 DMN 决策单测默认引擎 参数注入Test void test(DmnEngine dmnEngine) {...}只需在个别测试中使用引擎自定义配置RegisterExtensionDmnEngineExtension.forConfiguration(cfg)需要监听器、自定义 EL、指标收集器等JUnit 4DmnEngineRule存量 JUnit 4 项目camunda-dmn-junit5将「创建引擎 注入实例」的样板代码压缩为零依赖坐标一行、类注解一行、字段或参数一行。配合仓库内的 DmnEngineExtensionTest.java 与 RegisterDmnEngineExtensionTest.java 两个测试用例你可以直接作为模板开启 DMN 决策的单元测试之旅。【免费下载链接】camunda-bpm-platformCamunda 7 CE is End of Life (EoL). Please check out Camunda 8 instead (https://github.com/camunda/camunda) or read about Camunda 7 Enterprise End of Life (https://camunda.com/blog/2025/02/camunda-7-enterprise-end-of-life-extension/) – Camunda 7 CE was a flexible framework for workflow and decision automation using BPMN and DMN.项目地址: https://gitcode.com/GitHub_Trending/ca/camunda-bpm-platform创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考