Write unit tests for external tasks java class; trigger workers that subscribe to a topic and add unit tests

Hello,

I’m in the process of adding unit tests for my camunda workflow and was wondering how to add unit tests around an external task java class, that’s basically subscribed to multiple topics from my camunda workflow. I know how to add unit tests around the process modal, start, assert on a waiting scenario, complete and other aspects of testing a process modal itself, but i want to go 1 step further and trigger the worker that’s subscribed to a topic from my workflow and inturn test the business logic inside.

Using this repo and it’s example for process modal unit tests - https://github.com/camundacon2019/process-testing/blob/master/src/test/java/com/camundacon/tutorial/testing/bpmn/TestNextMatch.java

@Configuration
@Slf4j
public class DummyProcessWithMessage {

    private final String workerId;

    @Autowired
    RestTemplate restTemplate;

    public DummyProcessWithMessage(ClientProperties properties) {
        this.workerId = properties.getWorkerId();
    }

    @ExternalTaskSubscription(topicName = "task1")
    @Bean
    public ExternalTaskHandler task1ExternalTaskHandler() {
        return (externalTask, externalTaskService) -> {
        	log.info("*****************************************");
            log.info("handling task 1");
            // Call an external API and update some database fields to store the state of the current workflow
            // complete the supplierOnboarding task
            externalTaskService.complete(externalTask);
            log.info("{}: The external Task 1 {} has been checked", workerId, externalTask.getId());
            log.info("*****************************************");
        };
    }
    
    @ExternalTaskSubscription(topicName = "task2")
    @Bean
    public ExternalTaskHandler task2ExternalTaskHandler() {
        return (externalTask, externalTaskService) -> {
        	log.info("*****************************************");
            log.info("handling task 2");
            
            VariableMap variableMap = Variables.createVariables();
            variableMap.put("preference","steak");
            // gets triggered from a kafka message, and perform some external API calls.
            externalTaskService.complete(externalTask, variableMap);
            
            log.info("{}: The external Task 2 {} has been checked", workerId, externalTask.getId());
            log.info("*****************************************");
        };
    }
    
    @ExternalTaskSubscription(topicName = "cookPasta")
    @Bean
    public ExternalTaskHandler cookPastaExternalTaskHandler() {
        return (externalTask, externalTaskService) -> {
        	log.info("*****************************************");
            log.info("handling cook Pasta task");
            externalTaskService.complete(externalTask);
            // Poll an API and get the response from the external system and then update the tracking table for the same
            log.info("{}: The external Task cook Pasta {} has been checked", workerId, externalTask.getId());
            log.info("*****************************************");
        };
    }
}

I read this document on camunda docs that talks about different scopes of performing testing, but i can’t find next document for integration tests - Testing | docs.camunda.org

Hello @kallsas ,

as the External Task Handler is pure integration, I would use it as a pure mapper. It takes variables from the task and calls a service/bean that actually runs the business logic. This service/bean can then be tested as Unit Test as well.

By asserting during the process test that all required variables exist at a certain point, you can make sure the External Task Handler works as well.

Another option is to use a Mocking Framework to create ExternalTask and ExternalTaskService objects, invoke your External Task Handler with them and then do assertions on them.

I hope this helps

Jonathan