Mocking Dependencies for JavaDelegates

I am trying to write tests for my JavaDelegates. I am following the advice on this link:

https://camunda.com/best-practices/testing-process-definitions/#_mock_the_business_service_methods

I am not sure I can use constructor injection (which I would prefer over auto wired) given that the BPMN engine does not know what to inject. I notice that in the example the

@Inject

and

@Named

Attributes are used, but I am not sure which frameworks this is referring to. There is no indication in the documentation about which frameworks are used or supported and makes a lot of assumptions.

  • Is there any worked examples as to how I can do this?
  • I am using Unit with Mockito. Which IOC framework is recommended for this stack?

Thank you.

EDIT:
I have the testing working as such, but I am still unclear if the @AutoWired works in the ProcessEngine:

@RunWith(MockitoJUnitRunner.class)
public class SendWelcomeLetterDelegateTest {

    @InjectMocks
    SendWelcomeLetterDelegate sendWelcomeLetterDelegate;

    @Mock
    DelegateExecution executionMock;

    @Mock
    ConfigService configService;

    @Test
    public void executeTest() {
        try {
            sendWelcomeLetterDelegate.execute(executionMock);
        } catch (Exception e) {
            e.printStackTrace();
            Assert.fail();
        }
    }

}
@Component
public class SendWelcomeLetterDelegate implements JavaDelegate {

    @Autowired
    ConfigService configService;
...

EDIT 2:
I am finding that the Tomcat Camunda version does not wire up the Spring @Autowired components and am getting a SendWelcomeLetterDelegate.configService is null error when the process task executes.

java.lang.NullPointerException: Cannot invoke "za.co.services.ConfigService.getVpServerURL()" because "this.configService" is null
	at za.co.flow.delegates.SendWelcomeLetterDelegate.execute(SendWelcomeLetterDelegate.java:45)
	at org.camunda.bpm.engine.impl.bpmn.delegate.JavaDelegateInvocation.invoke(JavaDelegateInvocation.java:40)
	at org.camunda.bpm.engine.impl.delegate.DelegateInvocation.proceed(DelegateInvocation.java:58)
	at org.camunda.bpm.engine.impl.delegate.DefaultDelegateInterceptor.handleInvocationInContext(DefaultDelegateInterceptor.java:92)
...

Hi @SlappyAUS,

@Inject and @Named are from the javax. package and mainly use in CDI.

In my spring boot application use @Component instead of @Named, but keep the @Inject for constructor injection. And it worked successfully.

The test looks like this:

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;

import static org.camunda.bpm.engine.test.assertions.ProcessEngineTests.*;

import org.camunda.bpm.engine.test.mock.Mocks;
import org.camunda.bpm.extension.process_test_coverage.junit5.ProcessEngineCoverageExtension;

import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;

@ExtendWith(ProcessEngineCoverageExtension.class)
public class ProcessJUnitTest { 
  
  @Mock
  private TweetService mockedtweetService;
  
  @BeforeEach
  public void initMocks() {
    MockitoAnnotations.openMocks(this);
  }

  @Test
  @Deployment(resources = {"twitter-qa.bpmn", "tweetApproval.dmn"})
  public void testHappyPath() throws TwitterException {
    Mocks.register("createTweetDelegate", new CreateTweetDelegate(mockedtweetService));
    Mockito.when(mockedtweetService.publish(anyString())).thenReturn(100L);
...

I removed some imports for brevity.

Hope that helps, Ingo

This helps immensely.
However I would also like to see some of the corresponding code for the CreateTweetDelegate. I am not sure how the ProcessEngine instantiates the JavaDelegates and so I didn’t know if it required a default constructor or not?

Are you able to show me how the CreateTweetDelegate is wired up for constructor injection?

Thank you a LOT, there is not much end to end examples on this around.

EDIT: I am also only needing to test CreateTweetDelegate in isolation, so although your example uses it in the context of the engine, I only need use it as a standard test.