Autowired JPA Repository NULL in service task (while testing)

Hello.

I am developer and i want to teach Camunda BPM to our apprenticies. So i set up a Camunda Spring Boot app:

https://bitbucket.org/education-new/employeemanagerspringboot/admin

Please have a look at the ‘CreateCompanyDelegate’:


package de.sternico.employeemanager.server.delegate;

import javax.inject.Named;

import org.apache.log4j.Logger;
import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.springframework.beans.factory.annotation.Autowired;

import de.sternico.employeemanager.server.BpmnDefinitions;
import de.sternico.employeemanager.server.delegate.base.EmployeeManagerDelegate;
import de.sternico.employeemanager.server.entity.Company;
import de.sternico.employeemanager.server.repository.CompanyRepository;

@Named
public class CreateCompanyDelegate extends EmployeeManagerDelegate
{
private static final Logger logger = Logger.getLogger(CreateCompanyDelegate.class);

@Autowired
private CompanyRepository companyRepository;

@Override
public void execute(DelegateExecution execution) throws Exception
{
    // will be null in a camunda test scenario!!
    if (companyRepository != null)
    {
        String companyName = (String) execution.getVariable(BpmnDefinitions.Variables.COMPANY_NAME);
        Company company = new Company();
        company.setName(companyName);
        companyRepository.save(company);
        System.out.println("created a company [" + companyName + "]...yeah!!!");
    }
}

}

Running the spring boot app, it works fine and persists a Company object in h2 database. Running e.g. the test ‘CompanyProcessTest’ → (testApproveCompany())


package de.sternico.employeemanager;

import static org.camunda.bpm.engine.test.assertions.bpmn.BpmnAwareTests.assertThat;

import org.camunda.bpm.engine.runtime.ProcessInstance;
import org.camunda.bpm.engine.test.Deployment;
import org.camunda.bpm.engine.test.ProcessEngineRule;
import org.camunda.bpm.extension.process_test_coverage.junit.rules.TestCoverageProcessEngineRuleBuilder;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import de.sternico.employeemanager.server.BpmnDefinitions;
import de.sternico.employeemanager.server.util.MapBuilder;

@RunWith(SpringJUnit4ClassRunner.class)
// @DataJpaTest
// @EnableJpaRepositories(basePackages = “de.sternico.employeemanager.server.repository”)
@Deployment(resources = “ApproveCompanyProcess.bpmn”)
public class CompanyProcessTest extends EmployeeManagerTest
{
@Rule
@ClassRule
public static ProcessEngineRule processEngine = TestCoverageProcessEngineRuleBuilder.create().build();

// works if the test is marked as '@DataJpaTest', but not in the
// process engine test context...
// @Autowired
// private CompanyRepository companyRepository;

@Test
public void testApproveCompany()
{
    ProcessInstance instance = processEngine.getRuntimeService()
            .startProcessInstanceByKey(BpmnDefinitions.ProcessKeys.APPROVE_COMPANY_PROCESS);

    assertThat(instance).isWaitingAt(BpmnDefinitions.Tasks.TASK_APPROVE_COMPANY);
    processEngine.getTaskService()
            .complete(getTask(processEngine, instance, BpmnDefinitions.Tasks.TASK_APPROVE_COMPANY).getId(),
                    MapBuilder.getInstance().addEntry(BpmnDefinitions.Variables.COMPANY_APPROVED, true).create());
    assertThat(instance).hasPassed(BpmnDefinitions.Tasks.TASK_CREATE_COMPANY);
    assertThat(instance).isEnded();
}

@Test
public void testDeclineCompany()
{
    ProcessInstance instance = processEngine.getRuntimeService()
            .startProcessInstanceByKey(BpmnDefinitions.ProcessKeys.APPROVE_COMPANY_PROCESS);
    assertThat(instance).isWaitingAt(BpmnDefinitions.Tasks.TASK_APPROVE_COMPANY);
    processEngine.getTaskService()
            .complete(getTask(processEngine, instance, BpmnDefinitions.Tasks.TASK_APPROVE_COMPANY).getId(),
                    MapBuilder.getInstance().addEntry(BpmnDefinitions.Variables.COMPANY_APPROVED, false).create());
    assertThat(instance).hasNotPassed(BpmnDefinitions.Tasks.TASK_CREATE_COMPANY);
    assertThat(instance).isEnded();
}

}

the companyRepository in the delegate is not autowired and NULL. Could you tell me how to avoid that?

Thanks,
Stefan

You are manually setting up the process engine (the rule). This engine is not connected to spring and does not know about autowired properties.

You should switch to constructor injection for the delegate, initialize it in your test by passing the repository and then register it at the engine via Mocks.register(name, instance).

Hello, thank you. Do you know a link to an example for doing so?

Check out the best practice guide on testing … Camunda Best Practices - Testing Process Definitions

Plenty of good stuff there

Hello, Jan. I managed it, thanks for the help. I made a new setup where i have 2 tests:

1.) ControllerTest

Tests the web layer of my spring boot app along with the process engine. Works fine.

2.) BpmnDataJpaTestTest

I did like you said, i inject a repository into my delegates so that i can use them there. When i start the test separated from a clean install maven build (using junit 4), it works fine. The only thing left is that if i do a full build of the project, this test is not executed (only the ‘ControllerTest’).

If i switch from @Test (–> org.junit.Test) to @Test (org.junit.jupiter.api.Test) (which i use in the ControllerTest), the BpmnDataJpaTestTest will be executed by maven, but it fails (processEngine.getRuntimeService() gives me NULL).

Could you please have a short look?

https://bitbucket.org/education-new/springbootbpmncomplete/src/master/

I am running JDK 11.0.10.

Thanks, Stefan

I would stick with junit4 until you manage to get everything running and then do a junit5 migration.

Why? The default camunda testing is based on the camunda rule (which is a junit4 concept). Junit5 is supported by a community extension, but not by the core product.

When you switch from junit4 to junit5, the RunWith annotation becomes useless … you need to use ExtendWith … that’s probably the reason why your test is ignored …

So my advise: one step at a time … remove junit5, use the official, documented testing strategies … and when you are satisfied, take an afternoon to explore migration from junit4 to junit5 and restructure your dependencies.

1 Like