Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use ProcessEngineRule in a Junit test for Camunda Spring Boot application?

I try to run JUnit test for a Camunda Spring Boot application. I followed Testing:

JUnit 4

Using the JUnit 4 style of writing unit tests, the ProcessEngineRule must be used. Through this rule, the process engine and services are available through getters. As with the ProcessEngineTestCase (see above), including this rule will look for the default configuration file on the classpath. Process engines are statically cached over multiple unit tests when using the same configuration resource.

The following code snippet shows an example of using the JUnit 4 style of testing and the usage of the ProcessEngineRule.

public class MyBusinessProcessTest {

  @Rule
  public ProcessEngineRule processEngineRule = new ProcessEngineRule();

  @Test
  @Deployment
  public void ruleUsageExample() {
    RuntimeService runtimeService = processEngineRule.getRuntimeService();
    runtimeService.startProcessInstanceByKey("ruleUsage");

    TaskService taskService = processEngineRule.getTaskService();
    Task task = taskService.createTaskQuery().singleResult();
    assertEquals("My Task", task.getName());

    taskService.complete(task.getId());
    assertEquals(0, runtimeService.createProcessInstanceQuery().count());
  }
}

But I get an error:

org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [activiti.cfg.xml]; nested exception is java.io.FileNotFoundException: class path resource [activiti.cfg.xml] cannot be opened because it does not exist
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:344)
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:304)
    at org.camunda.bpm.engine.impl.cfg.BeansConfigurationHelper.parseProcessEngineConfiguration(BeansConfigurationHelper.java:35)
    at org.camunda.bpm.engine.impl.cfg.BeansConfigurationHelper.parseProcessEngineConfigurationFromResource(BeansConfigurationHelper.java:50)
    at org.camunda.bpm.engine.ProcessEngineConfiguration.createProcessEngineConfigurationFromResource(ProcessEngineConfiguration.java:305)
    at org.camunda.bpm.engine.ProcessEngineConfiguration.createProcessEngineConfigurationFromResource(ProcessEngineConfiguration.java:301)
    at org.camunda.bpm.engine.impl.test.TestHelper.getProcessEngine(TestHelper.java:428)
    at org.camunda.bpm.engine.test.ProcessEngineRule.initializeProcessEngine(ProcessEngineRule.java:175)
    at org.camunda.bpm.engine.test.ProcessEngineRule.apply(ProcessEngineRule.java:154)
    at org.junit.rules.RunRules.applyAll(RunRules.java:26)
    at org.junit.rules.RunRules.<init>(RunRules.java:15)
    at org.junit.runners.BlockJUnit4ClassRunner.withTestRules(BlockJUnit4ClassRunner.java:400)
    at org.junit.runners.BlockJUnit4ClassRunner.withRules(BlockJUnit4ClassRunner.java:356)
    at org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:278)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)
Caused by: java.io.FileNotFoundException: class path resource [activiti.cfg.xml] cannot be opened because it does not exist
    at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:172)
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:330)
    ... 27 more

I could add activiti.cfg.xml, but it would not be used by my Camunda Spring Boot application. It feels wrong, to add a file to non-testing source only for testing. It would also violate DRY, because I would have to synchronize both configurations.

Is there another way to use ProcessEngineRule in my JUnit test?

like image 613
dur Avatar asked Aug 03 '18 09:08

dur


2 Answers

You can instantiate the rule with an engine like this, then Camunda does not try to read from the cfg.xml file:

 @Rule
 public final ProcessEngineRule camunda = new ProcessEngineRule(myConfiguration.buildProcessEngine());

where myConfiguration is an instance of ProcessEngineConfiguration that you create as you like.

If you are using the Spring Boot runner, try importing the camunda-spring-boot-starter-test dependency and use the StandaloneInMemoryTestConfiguration helper for this:

@Rule
public final ProcessEngineRule camunda = new StandaloneInMemoryTestConfiguration().rule();
like image 101
Jan Galinski Avatar answered Oct 27 '22 00:10

Jan Galinski


Do you use @EnableProcessApplication for your application? If yes, I think you actually don't need org.camunda.bpm.engine.test.ProcessEngineRule any more:

  • You can get the RuntimeService via @Autowired RuntimeService runtimeService;
  • You can get the ProcessEngine via BpmPlatform.getDefaultProcessEngine()

But anyhow, if you really want to use the rule:

Write your own class:

public class MyProcessEngineRule extends ProcessEngineRule {

    @Override
    public Statement apply(Statement base, Description description) {
        // you can use this, if you use AbstractAssertions
        // super.processEngine = AbstractAssertions.processEngine(); 
        super.processEngine = processEngine();
        return super.apply(base, description);
    }

    public static ProcessEngine processEngine() {
        Map<String, ProcessEngine> processEngines = ProcessEngines.getProcessEngines();
        if (processEngines.size() == 1) {
            return processEngines.values().iterator().next();
        } else {
            throw new IllegalStateException("some usefule message");
        }
    }
}

and use @Rule public MyProcessEngineRule rule = new MyProcessEngineRule(); in your testclass.

At least, that worked for me...

like image 32
markus_ Avatar answered Oct 27 '22 00:10

markus_