How to set up Camunda for unit testing in Spring Boot - java

I am able to run a Spring Boot application with Camunda for workflow management. My pom.xml with Camunda related dependencies are shown below.
<dependencyManagement>
...
<dependency>
<groupId>org.camunda.bpm</groupId>
<artifactId>camunda-bom</artifactId>
<version>7.15.0</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
<dependency>
<groupId>org.camunda.bpm.springboot</groupId>
<artifactId>camunda-bpm-spring-boot-starter</artifactId>
<version>7.15.0</version>
</dependency>
<!-- REST API -->
<dependency>
<groupId>org.camunda.bpm.springboot</groupId>
<artifactId>camunda-bpm-spring-boot-starter-rest</artifactId>
<version>7.15.0</version>
</dependency>
<!-- dashboard -->
<dependency>
<groupId>org.camunda.bpm.springboot</groupId>
<artifactId>camunda-bpm-spring-boot-starter-webapp</artifactId>
<version>7.15.0</version>
</dependency>
<dependency>
<groupId>org.camunda.bpm</groupId>
<artifactId>camunda-engine-plugin-spin</artifactId>
</dependency>
<dependency>
<groupId>org.camunda.spin</groupId>
<artifactId>camunda-spin-dataformat-all</artifactId>
</dependency>
I have just one .BPMN file. My application.yml file looks like this:
spring.main.banner-mode: console
server.port: 9090
springdoc:
model-and-view-allowed: true
swagger-ui:
operationsSorter: alpha
spring.jpa:
hibernate:
ddl-auto: none
show-sql: true
properties:
hibernate:
format_sql: true
spring.datasource:
initialization-mode: always
platform: postgres
url: jdbc:postgresql://xxxx
username: xxxx
password: xxxx
spring.flyway.enabled: false
camunda.bpm:
admin-user:
id: demo
password: demo
generic-properties:
properties:
generalResourceWhitelistPattern: "[a-zA-Z0-9,'_\\$\\-\\.\\+\\!\\*\\(\\)]+|camunda-admin"
In the codes, all I have to do are just to declare the Camunda objects and I can used them without further setups:
#AutoWired
protected final RuntimeService runtimeService;
#AutoWired
protected final TaskService taskService;
#AutoWired
protected final IdentityService identityService;
Now I am trying to write unit tests. It seems that there are more than one way to set up Camunda for unit testing, but I am not able to get any of the examples I found working. By some trial and error, I managed to get the following codes to set up Camunda for unit test.
#ActiveProfiles("test")
public class EntitlementServiceTest {
private RuntimeService runtimeService;
private TaskService taskService;
private IdentityService identityService;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
ProcessEngine processEngine = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration()
.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE)
.setJdbcUrl("jdbc:h2:mem:database_user;DB_CLOSE_ON_EXIT=FALSE")
.setJobExecutorActivate(true)
.buildProcessEngine();
runtimeService = processEngine.getRuntimeService();
taskService = processEngine.getTaskService();
identityService = processEngine.getIdentityService();
}
...
}
But I am not sure if this is the correct way to do so, so it would be better if someone points this out. The codes don't seem to have loaded anything from the application file for unit testing, application-test.yml. Replacing the hardcoded JDBC URL with ${spring.datasource.url} does not work at all. And even though I have set the camunda.bpm.generic-properties.properties.generalResourceWhitelistPattern, application-test.yml, it is obvious that it is not being read.

You have basically two ways to test a camunda spring boot application:
1st: run a camunda engine in memory, without spring. This can be very useful to test process flows, delegate behavior and so on. In that case, you will use the "ProcessEngineRule" from the core (junit4 style) or the junit5 extension (camunda-bpm-junit5). You will probably mock a lot of services and repos because you focus on the camunda flow. You do not need to annotate with "ActiveProfiles", as you are not running a spring context.
2nd: Run your tests using the SpringRunner or the SprinExtension and let spring handle the engine setup. This is just a plain spring boot test which will run everything you specify via yml and profiles and you will be able to inject all the camunda services.
Neither of these approaches is "better", they focus on different things. According to the testing pyramid, you would have many "real" unit tests, that do not even run camunda in memory just to verify your code works, some rule-based flow tests and a few integration tests using spring boot tests.
The camunda best practices guide will help configuring the scenarios: https://camunda.com/best-practices/testing-process-definitions/
Sidenote: When you mix plain-unit and spring integration tests, you should switch to constructor based injection to make it easier to manually create instances of your services without using reflection.

Related

DataBase Testing By using Autowire in Integration Testing

I am new to DataBase testing and I am trying to Connect the database by using tag #SpringBootTest in class level and by using Autowire, It is not creating instantiation getting always null
#SprintBootTest
Class Test{
#Autowire
DatabaseService databaseService;
}
Can anyone suggest please? If any one did similar like this , can you please give me the instructions
There are multiple ways to test your database and here is a couple of them,
Using In-memory-database(ex: H2) using test scope
It's quite good to use h2(in-memory-DB) for mimicking the database. Though it is not mandatory and we can use mockito to mock the database interactions as well.
Add these dependencies,
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.196</version>
<scope>test</scope>
</dependency>
Now your test class should look like this,
#RunWith(SpringRunner.class)
#SpringBootTest(classes = YourApp.class, webEnvironment = RANDOM_PORT)
Class DatabaseServiceTest{
#Autowired
private DatabaseService databaseService;
}
Replicating actual database configuration properties
First, you need to replicate your properties/yml from main/resources to test/resources directory. Your test class remains the same as given in the above approach. But make sure that you excluded the h2-dependency from your pom.
Please explore these tutorials as well,
spring integration testing
spring boot test
junit and mockito example

How to add BlockHound to a spring boot app to detect blocking calls?

How to add BlockHound to spring boot app to detect blocking calls ?
I didn't find any examples for spring boot apps:
https://github.com/reactor/BlockHound/blob/master/docs/quick_start.md
Any help will be appreciated.
IMHO, the wisest choice would be to enable BlockHound while the code is being exercised by JUnit tests.
To do so you simply need to import the https://mvnrepository.com/artifact/io.projectreactor.tools/blockhound-junit-platform dependency with test scope, which automatically initializes BlockHound when you launch your JUnit tests suite:
<dependency>
<groupId>io.projectreactor.tools</groupId>
<artifactId>blockhound-junit-platform</artifactId>
<version>1.0.0.RC1</version>
<scope>test</scope>
</dependency>
Alternatively, if you intend to use BlockHound at all times - and not only during tests - you should instead import the following dependency:
<dependency>
<groupId>io.projectreactor.tools</groupId>
<artifactId>blockhound</artifactId>
<version>1.0.0.RC1</version>
</dependency>
And call BlockHound.install() in your main method, just before bootstrapping your Spring Boot application:
#SpringBootApplication
public class BlockhoundDemoApplication {
public static void main(String[] args) {
BlockHound.install();
SpringApplication.run(BlockhoundDemoApplication.class, args);
}
}
For further reference you can refer to:
my article # https://medium.com/#domenicosibilio/blockhound-detect-blocking-calls-in-reactive-code-before-its-too-late-6472f8ad50c1 where I explain how to integrate and customize BlockHound for JUnit testing in a Spring Boot 2.2 application;
my demo project over at GitHub that integrates and customizes BlockHound for JUnit testing;
the BlockHound docs (see the supported testing frameworks section);
the BlockHound Gitter channel, where you can ask questions about BlockHound.

Sprint Boot ProducerTemplate as constructor parameter failing

Edit: I've been told by my lead that the test that called the class I was having issues with utilized BPMS and that BPMS is no longer used for the project. Thank you for all of the replies.
Background:
I'm working with an existing codebase, which still isn't fully functional. Specifically, I've been tasked with getting the project's unit tests completed, but I've had no previous experience with Spring or dependency managers at all.
Problem:
The code given below is causing my tests to not compile, saying there's no qualifying bean of ProducerTemplate.
#Component
public class QueueService {
#Produce
private ProducerTemplate producerTemplate;
public QueueService(ProducerTemplate producerTemplate) {
this.producerTemplate = producerTemplate;
}
}
I'm sorry if this is a dumb question, but I haven't been able to find another instance of this in a question.
Stack Trace
Spring Boot component provides auto-configuration for Apache Camel. For integration using Apache Camel you must add a starter dependency:
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
<version>2.22.1</version>
</dependency>
See here for more info. A tutorial on the subject.

Mockito 2 - SpringBoot 1.5.11.RELEASE - Could not initialize class org.mockito.Mockito

I am trying to mock the final class which is available in our company's internal library using Mockito 2.18.3 framework, unfortunately we don't have access to change the code in the library. But whenever I run I get below error:
java.lang.NoClassDefFoundError: Could not initialize class org.mockito.Mockito
at org.springframework.boot.test.mock.mockito.MockReset.get(MockReset.java:107)
at org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener.resetMocks(ResetMocksTestExecutionListener.java:69)
at org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener.resetMocks(ResetMocksTestExecutionListener.java:55)
at org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener.afterTestMethod(ResetMocksTestExecutionListener.java:50)
at org.springframework.test.context.TestContextManager.afterTestMethod(TestContextManager.java:319)
This is my dependency:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.18.3</version>
<scope>test</scope>
</dependency>
This is the test class:
#RunWith(SpringRunner.class)
#TestPropertySource("classpath:application-test.properties")
#SpringBootTest
public class JwtTokenTest {
#Autowired
private class JwtValidatorService jwtValidatorService;
#Mock
private JwtTokenDetails jwtTokenDetails;
#Test
public void jwtGenerateTest() {
//Code to test JWT generation
}
}
Also as per this link: https://github.com/mockito/mockito/wiki/What%27s-new-in-Mockito-2#unmockable I have created org.mockito.plugins.MockMaker file with contents: mock-maker-inline.
I tried searching in other Stackoverflow posts and Google, but still not solution. Can anyone kindly help me in this? Looks like I am missing something, but failed to identify it. Since I don't have much expertise in Mockito, tried to use powermock but it is posing different challenges in downloading dependencies in company's network.
Please let me know if I need to add more code or more details.
Spring Boot 1.5.11 is compatible with Mockito 1.x. Specifically, it uses 1.10.19. Rather than overriding the version of Mockito to a new major version, you should let Spring Boot's dependency management specify the version. Doing so will ensure that you use a compatible version. If Mockito 1.10 doesn't meet your needs, you'll need to find an alternative solution.
Spring Boot uses Mockito 1.x by default. However, it's possible to override it with Mockito 2.x, as Spring Boot can also use it without any problems (see this commit).
To do so, just add this modification to your POM file properties:
<properties>
<mockito.version>2.18.3</mockito.version>
</properties>

CXF (SOAP) Web Services integration test

Just implemented the SOAP Web Service using CXF. It is easy for me to write some unit tests using the mock framework. But not quite sure what's the best way to write some integration test for my web services. The implementation is something like this:
#Autowired
private InvoiceService invoiceService;
#Webservice(endpointinterface="xxx")
public Invoice retrieveInvoiceById(String id) {
Invoice invoice = invoiceService.getInvoiceById(id);
return invoice;
}
The InvoiceService will invoke the method to retrieve the invoice from a text file or some file system and then return. So how should I write the integration test to test the whole?
Thanks guys.
Write your unit tests so that the actual test will start Jetty server and expose your web service as real endpoint during test run. If you are using any database, use Derby or some other database which supports in-memory feature.
For e.g. just declare your endpoint in your test context spring file:
<jaxws:endpoint id="someProxy"
implementor="#yourWebServiceImplBean"
wsdlLocation="src/main/webapp/WEB-INF/wsdl/InvoiceService.wsdl"
address="http://0.0.0.0:12345/YourService/services/InvoiceService"/>
This is enough to start Jetty instance and expose your web service. This will start Jetty instance on port: 12345. Autowire this bean into your test class and you are ready to call methods.
Also you need to include this dependency in order Jetty to be run in unit tests.
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>${cxf.version}</version>
<scope>test</scope>
</dependency>

Categories