Testing processes with junit in spring

If someone is interested in the subject, I’ve written a little article about unit testing processes here with following parts:

  1. Asserting paths of process execution
  2. Mocking service tasks
  3. How to test call activities in isolation with proper exception handling
  4. How to mock call activity results
1 Like

After looking at your tutorial, I tried to test my processes in similar way, but in Java. However, I am unable to mock the service task. My test runs the actual service task instead of the mock. I have also built TestConfiguration for MockExpressionManager, but still does not work.

Test

@RunWith(SpringRunner.class)
@SpringBootTest
public class PortfolioProcessTest {

@Autowired
private RuntimeService runtimeService;

@Test
public void startPortfolioProcess(){
    prepareEnv();
    this.runtimeService.startProcessInstanceByKey("portfolioReconfigurationProcess",getProcessStartVariable());
}

public void prepareEnv(){
     MailService mockMailService = mock(MailService.class);
     when(mockMailService.sendMail()).thenReturn("Sending Mail");
     Mocks.register("rejectMailPms",new RejectMailPms(mockMailService));
}  

ServiceTask
@Service
public class RejectMailPms {

MailService mailService;

@Autowired
public RejectMailPms(MailService mailService){
    this.mailService = mailService;
}

public void sendMail(){
    System.out.println(mailService.sendMail());
}

}

MailService
@Service
public class MailService {

public String sendMail(){
    return  null;
}

}

@Configuration
public class TestConfiguration {

@Bean
public EngineConfigurationConfigurer<SpringProcessEngineConfiguration> flowableTestSpringProcessEngineConfig(){
    return new MyConfigurer();
}

}

public class MyConfigurer implements EngineConfigurationConfigurer {

public void configure(SpringProcessEngineConfiguration processEngineConfiguration) {
    // advanced configuration
    processEngineConfiguration.setExpressionManager(new MockExpressionManager());
}

}

It looks everything is done correctly here, so I don’t know what doesn’t work. The only thing you haven’t shown is how the bean is called in the process definition - is it done by the EL expression?

If it is, the only thing I can think of is that something is not initialized properly. If you look into MockExpressionManager you will see its order of resolvers:

        CompositeELResolver compositeElResolver = new CompositeELResolver();
        compositeElResolver.add(new ProcessVariableScopeELResolver(variableContainer));
        compositeElResolver.add(new MockElResolver());
        compositeElResolver.add(new ArrayELResolver());
        compositeElResolver.add(new ListELResolver());
        compositeElResolver.add(new MapELResolver());
        compositeElResolver.add(new BeanELResolver());
        compositeElResolver.add(new CouldNotResolvePropertyELResolver());

Where MockElResolver uses Mocks.get() to get your bean. Try to stop there with a breakpoint to check if it’s even called. If not, something is wrong with your initialization and the MockExpressionManager bean is not used.

My expression for the service task is as follows
flowable:expression="#{rejectMailPms.sendMail()}"

in

serviceTask id=“rejectMailService” name=“Send Reject Mail” flowable:expression="#{rejectMailPms.sendMail()}"></serviceTask

Also I kept the breakpoint where MockElResolver uses Mocks.get(). It does not reach there.
However,MockExpressionManager gets initialized but the method “createElResolver(VariableContainer variableContainer)” is not called.

public class MyConfigurer implements EngineConfigurationConfigurer {

public void configure(SpringProcessEngineConfiguration processEngineConfiguration) {
    // advanced configuration
    MockExpressionManager mockExpressionManager = new MockExpressionManager();
    processEngineConfiguration.setExpressionManager(mockExpressionManager);
}

Unfortunately from my point of view this should work and I cannot see any bugs in the above code. Maybe something has been changed in Flowable?

I can hint you with following things only:

  1. In my BPMN editor flowable used activity namespace not flowable, for example <serviceTask id="banUserTask" name="Ban user" activiti:expression="#{banUserServiceTask.ban(userId)}"></serviceTask>
  2. Before MockElResolver you have ProcessVariableScopeELResolver - is this possible that you have the process variable named rejectMailPms which points to the original bean? If so, it’d be resolved by this resolver.
  3. If MockExpressionManager.createElResolver() isn’t even called, you probably work with DefaultExpressionManager. You can stop with breakpoint in its createElResolver() method and check. If so, you need to dig deeper to find out why your MockElResolver is not properly registered in flowable engine with this configuration.