我正在尝试将单个规则作为一个单元运行,以便测试我的应用程序 . 我们作为单位运行的原因是因为这些规则包含一些非常复杂的业务逻辑,需要进行全面测试 . 我们确实有其他测试作为一个整体运行整个会话,但这些测试的细粒度不足以涵盖单个规则的业务逻辑 . 所以我们已经完成了所有“不要测试个别规则”的文章,但由于我们的特定用例,我们已经决定了 .

无论如何,我遇到的实际问题是我们试图应用的RuleNameEqualsAgendaFilter似乎没有我们希望的预期行为 . 虽然我已经指定了重点议程组并且在运行规则时也应用了过滤器,但所有规则似乎都要进行评估 . 这导致无法测试两个在相同条件下发射的规则 .

我已经包含了我的测试代码和一些示例规则,这些规则在结构上类似于我们的运行方式 .

Test

@Slf4j
public class MyUnitTest {

  @Test
  public void myRuleTest() {
    MyFact myFact = new MyFact();

    KieSession kieSession = getKieSessionWithFacts("myAgendaGroup", myFact);

    fireSpecificRule(kieSession, "My First Rule");
  }

  private KieSession getKieSession(String agendaGroup) {
    KieServices kieServices = KieServices.Factory.get();
    KieContainer kieContainer = kieServices.getKieClasspathContainer();
    KieSession kieSession = kieContainer.newKieSession("TEST");
    kieSession.setGlobal("logger", log);
    kieSession.getAgenda().getAgendaGroup(agendaGroup).setFocus();
    return kieSession;
  }

  private KieSession getKieSessionWithFacts(String agendaGroup, Object... facts) {
    KieSession kieSession = getKieSession(agendaGroup);
    for (Object fact : facts) {
      kieSession.insert(fact);
    }
    return kieSession;
  }

  private void fireSpecificRule(KieSession kieSession, String ruleName) {
    kieSession.fireAllRules(new RuleNameEqualsAgendaFilter(ruleName));
  }

}

Rules

rule "My First Rule"
agenda-group "myAgendaGroup"
no-loop true
when
    MyFact()
then
    logger.info("Fired my first rule");
end

rule "My Second Rule"
agenda-group "myAgendaGroup"
no-loop true
when
    MyFact()
then
    logger.info("Fired my second rule");
end

rule "My Unrelated Rule"
agenda-group "myOtherAgendaGroup"
no-loop true
when
    MyFact()
then
    logger.info("Fired my unrelated rule");
end

我们在测试日志中看到的输出如下:

  • 解雇了我的第一条规则

  • 解雇了我的第二条规则

  • 解雇了我无关的规则

这意味着过滤器不仅不会限制myAgendaGroup中的哪些规则被触发,而且还会触发myOtherAgendaGroup中的规则 .

我希望能够解雇第一条规则 . 我错过了什么?