mockito 2 strict mode

further to https://lwpro2.wordpress.com/2023/05/22/mockito-for-java-17/, another breaking change with mockito 2 is the strict vs lenient mode for any unused stub.

the changes:

add lenient() at the statement:

somehow neither annotation worked:

so lenient() is the only workable solution here.

mockito for java 17

following up https://lwpro2.wordpress.com/2023/05/14/java-8-to-java-17-migration-for-a-large-monolithic/, there are further bugs to fix with the existing implementation with Mockito (somehow the existing codebase used mockito, together with easyMock, PowerMock as well).

The workable versions are :

in addition,

  1. switching from mockito 1 to 2, it now stops matching null with any. so the solution is to wrap it with nullable.

2. another breaking change is, mockito 2 doesn’t match array with any. the solution is to cast with any(Object[].class)

3. Mockito anyCollection().toArray() is no longer matching with array

java 8 to java 17 migration for a large monolithic

for a simple microservices, to migrate from java 8 to java 17, could be as simple as 1) upgrading jdk 2) upgrade necessary libraries

however, for a monolithic application upgrade, it would require a lot of effort to fix the library compatibility issue.

At the moment, the application I am trying to migrate has a lot of code smell and anti patterns, for example, there are circular definition in the spring XML definition:

the service bean has a reference to a schedler bean, which circular back for a reference to the service bean.

the fix/hack for this problem is to force spring to allow circular reference (due to the implementation, lazy init is also not working)

similarly, due to the implementation, bean definition overriding has also to be enaled

spring.main.allow-bean-definition-overriding=true

spring: 
  main:
    allow-circular-references: true

refer: https://lwpro2.wordpress.com/2021/03/22/spring-circular-reference/

spring contract (cdc) consumer

CDC testing would shift left and help the developers move fast through testing (UAT & integration testing).

following up to previous article, https://lwpro2.wordpress.com/2023/03/26/spring-contract-for-cdc/, this will show an example how to use the CDC from a consumer perspective.

  1. import the spring stub runner and wiremock library

2. config the sub mode (local or remote), and where/what to download if remote

3. Spring Stub runner would then download the stub, and start the wiremock server with the contract. The test class could then use the wiremock server for testing:

broken unit test with easyMock

there is a need to add in further logging, to assist the developer for troubleshooting an API call.

however, with such a simple logging statement, it broke the pipeline because a bug in the implementation with easyMock.

the new log line:

if the response is not null, log the status and header. otherwise log as null.

above small code changes however broke the CI/CD. after some investigation, it is found the original developer who coded the unit test, which supposed to protect the application, would break if the status method is not called 2 (a magic number) times.

The fix is, it really doesn’t need to hard code the times the method is called, instead it should use andStubReturn instead of andReturn method.

the fix

the problem with easyMock is (beside the clear no-go with replay/replayAll), the default andReturn method expect times of the call, which default is 1. the developer when implement the unit test at the time, has called the getStatus method 2 times, hence hardCode it with 2. this will break if any developer or use case, that the method needs to be called 1 or any times more.

While the correct method for easyMock to use is `andStubReturn

camunda spring integration

in newer versions of camunda engine, it’s able to invoke the external task through “`something called topic, similar concept as MQ/Kafka. (in addition to old approach of REST calls.)

However, to integrate camunda external client with Spring boot took me something to figure out. The integration with standalone java process is working fine, something like


Note: it seems like running multiple ExternalTaskClient with same engine (HTTP://localhost:8080/engine-rest here) on same JVM seems like not working.

however, with spring integration, it’s not able to subscribe to the topic. Where on camunda cockpit, the task would show messages # posted not yet consumed:

In Java, subscribe to the topic:

in config, tell where is the engine:

on cockpit, it would show # of messages posted, however, pending for consumption (2 messages here for example).

for each process instance, its pointing Extneral Tasks, which is the topic

turns out the problem and the solution is with the in-compataility between spring boot (an in-hour built library which is a wrapper of Spring boot) version and camunda external client.

The only needed dependency from camunda side:

to make it work, the spring boot version worked is 2.7.10 and below, version 3 above is not working:

speed up the CI/CD

the existing CI/CD process in the team is extremely slow, its always taking 20+ minutes to complete, and in extreme cases, its taking 50+ minutes.

These are some steps i am taking to speed up the process:

besides leveraging on maven parallel builds

mvn clean install/verify/package -T xC

the test stage could also be put into parallel mode in newer version of maven, the change is needed is:

    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>3.0.0</version>
    <configuration>
        <forkCount>3</forkCount>. <!---leverage on fork, which is spin up parallel process, instead of concurrent threads-->
        <reuseForks>true</reuseForks>
        <argLine>-Xmx1024m -XX:MaxPermSize=256m</argLine>
        <systemPropertyVariables>
            <databaseSchema>MY_TEST_SCHEMA_${surefire.forkNumber}</databaseSchema>
        </systemPropertyVariables>
        <workingDirectory>FORK_DIRECTORY_${surefire.forkNumber}</workingDirectory>
    </configuration>
  </plugin>

in addition, to the maven incrementalCompiliation.

the trick is false is for true, which is using incrementalCompilation.

spring contract for cdc

in the beginning, i was confused by why it’s called CDC (consumer driven testing). because in the end, the contract is put at the producer side, and protect the producer making any changes to break the contract.

after looking into this into more detail, then it turns out the contract is supposed to be written by consumer, hence the name of consumer driven.

anyway, its ultimately stopping the producer from making any breaking change which violate the contract.

the gist of the changes:

on the producer side:

  1. add the dependency

org.springframework.cloud
spring-cloud-starter-contract-verifier
test

2. add the plugin, this generates the test, which bind the producer to the contract

org.springframework.cloud
spring-cloud-contract-maven-plugin
${spring-cloud-contract.version}
true

com.example.contractTest.BaseTestClass

org.springframework.boot
spring-boot-maven-plugin

3. add the contract and the base class

on the consumer side:

  1. add the dependency (stub runner and wiremock)
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-contract-stub-runner</artifactId>
    <scope>test</scope>
</dependency>

2. add the test (pointing to the stub)

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment=WebEnvironment.NONE)
@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:+:stubs:6565"},
        stubsMode = StubRunnerProperties.StubsMode.LOCAL)
public class LoanApplicationServiceTests {

maven dependency vs dependencyManagement

I was trying to add some spring contract library onto classpath, however, after adding it to pom, did the refresh, and restarted the intellij all resulted in nothing.

finally realized I was putting the dependency into “`<dependencyManagement>`. section.

I’m fashionably late to this question, but I think it’s worth a clearer response than the accepted one (which is correct, but doesn’t emphasize the actual important part, which you need to deduce yourself).

In the parent POM, the main difference between the <dependencies> and <dependencyManagement> is this:

  • Artifacts specified in the <dependencies> section will ALWAYS be included as a dependency of the child module(s).
  • Artifacts specified in the <dependencyManagement> section, will only be included in the child module if they were also specified in the <dependencies> section of the child module itself. Why is it good you ask? Because you specify the version and/or scope in the parent, and you can leave them out when specifying the dependencies in the child POM. This can help you use unified versions for dependencies for child modules, without specifying the version in each child module.

Share

source: pom.xml – Differences between dependencyManagement and dependencies in Maven – Stack Overflow