When we mock a method that returns a Stream
we need to make sure we return a fresh Stream
on each invocation to support multiple calls to the mocked method. If we don’t do that, the stream will be closed after the first call and subsequent calls will throw exceptions. We can chain multiple thenReturn
calls to return a fresh Stream
each time the mocked method is invoked. Or we can use multiple arguments with the thenReturn
method, where each argument is returned based on the number of times the mocked method is invoked. So on the first invocation the first argument is returned, on second invocation the second argument and so on. This works when we know the exact number of invocations in advance. But if we want to be more flexible and want to support any number of invocations, then we can use thenAnswer
method. This method needs an Answer
implementation that returns a value on each invocation. The Answer
interface is a functional interface with only one method that needs to be implemented. We can rely on a function call to implement the Answer
interface where the function gets a InvocationOnMock
object as parameter and returns a value. As the function is called each time the mocked method is invoked, we can return a Stream
that will be new each time.
Continue reading →
A Gradle build file describes what is needed to build our Java project. We apply one or more plugins, configure the plugins, declare dependencies and create and configure tasks. We have a lot of freedom to organize the build file as Gradle doesn’t really care. So to create maintainable Gradle build files we need to organize our build files and follow some conventions. In this post we focus on organizing the tasks and see if we can find a good way to do this.
It is good to have a single place where all the tasks are created and configured, instead of having all the logic scattered all over the build file. The TaskContainer
is a good place to put all the tasks. To access the TaskContainer
we can use the tasks
property on the Project
object. Within the scope of the tasks
block we can create and configure tasks. Now we have a single place where all the tasks are created and configured. This makes it easier to find the tasks in our project as we have a single place to look for the tasks.
Continue reading →
The IntelliJ HTTP Client is very useful for testing APIs. We can use Javascript to look at the response and write tests with assertions about the response. If an API returns a JSON Web Token (JWT), we can use a Javascript function to decode the token and extract information from it. For example we can then assert that fields of the token have the correct value. There is no built-in support in IntelliJ HTTP Client to decode a JWT, but we can write our own Javascript function to do it. We then use the function in our Javascript response handler to decode the token.
Continue reading →
It is good practice in Gradle to use lazy configuration. This makes builds faster as only configuration values are evaluated when needed. We should try to not let Gradle spend time on evaluating configuration values that will not be used. For example tasks that are not executed could still be configured by Gradle. If we make sure the configuration of these tasks is lazy we can save time.
Gradle gives us a lazy way to get the value of a Java system property. In our build script we can use the providers
property of type ProviderFactory
and the method systemProperty(String)
. This method returns a Provider<String>
instance that can be used to get the value of a system property in a lazy way. The method systemProperty
can also be used with a Provider<String>
argument.
Continue reading →
It is good practice in Gradle to use lazy configuration. This makes builds faster as only configuration values are evaluated when needed. We should try to not let Gradle spend time on evaluating configuration values that will not be used. For example tasks that are not executed could still be configured by Gradle. If we make sure the configuration of these tasks is lazy we can save time.
Gradle gives us a lazy way to get the value of an environment variable. In our build script we can use the providers
property of type ProviderFactory
and the method environmentVariable(String)
. This method returns a Provider<String>
instance that can be used to get the value of an environment variable in a lazy way.
Continue reading →
When we use the IntelliJ HTTP Client we can write JavaScript for the pre-request and response handlers. If we want to access an environment variable in JavaScript we can use request.environment.get(string)
. The argument for the get
function is the name of the environment variable we want to get the value for. Environment variables can be defined in the file http-client.env.json
or in http-client.private.env.json
.
Continue reading →
The built-in IntelliJ HTTP Client is very useful for testing HTTP requests and responses. If we want to define a variable in our .http
file that is only used in this file and will not change per environment we can define it using the following syntax: @<variable name> = variable value
. The variable is an in-place variable and the scope of the variable in the current .http
file. The variable is immutable and can only be defined with a value once and cannot be overwritten. To refer to the variable we use the syntax {{}}
.
Continue reading →
The command line option --continuous
or the short version -t
enables Gradle’s continous build. For a continuous build Gradle will keep on running and will re-execute the tasks we invoked if the input or of the input of one of the depended tasks has changed. For a project with the java
plugin we can use this option for the test
task. Gradle will run the test
task and after the task has been executed Gradle will wait for any changes in the input of the task. This means if we change our Java test code in src/test/java
and save the source file Gradle will re-execute the test
task and show the output. But also if the input of other tasks changes, that the test
task depends on, the test
is re-executed. So also changes in source files in our src/main/java
directory will trigger a re-execute of the test
task, because the test
task depends on the compileJava
task, and the compileJava
task has the src/main/java
directory as input.
Continue reading →
With the java plugin we can configure a so-called Java toolchain. The toolchain configuration is used to define which Java version needs to be used to compile and test our code in our project. The location of the Java version can be determined by Gradle automatically. Gradle will look at known locations based on the operating system, package managers, IntellIJ IDEA installations and Maven Toolchain configuration.
But we can also define the locations of our Java installations ourselves using the project property org.gradle.java.installations.paths
. We provide the paths to the local Java installations as a comma separated list as value for this property. When we set this property we can also disable the Gradle toolchain detection mechanism, so only the Java installations we have defined ourselves are used. To disable the automatic detection we set the property org.gradle.java.installations.auto-detect
to false
. If we leave the value to the default value true
, then the locations we set via org.gradle.java.installations.paths
are added to the Java installations already found by Gradle.
The property org.gradle.java.installations.paths
is a project property we can set via the command line, but we can also set it in the gradle.properties
file in our GRADLE_USER_HOME
directory. Then the values we define will be used by all Gradle builds on our machine.
Continue reading →
When we apply the Java plugin to our Gradle project we can configure which Java version we want to use for compiling our source code and running our tests using a toolchain configuration. The benefit of having a toolchain configuration is that we can use a different Java version for compiling and running our code than the Java version that is used by Gradle to execute the build. Gradle will look for that Java version on our local computer or download the correct version if it is not available. To search for a local Java installation Gradle will look for operating system specific locations, installations by package managers like SKDMAN! and Jabba, IntelliJ IDEA installations and Maven Toolchain specifications. Maven Toolchain specifications is an XML file describing the location of local Java installation. Each Java installation is described by a version and optional vendor it provides and the location of the installation. Maven uses this information to find the correct Java installation when the maven-toolchain-plugin
is used in a Maven project. But Gradle can also utilize Maven Toolchain specifications to find local Java installations. This can be useful when we have to work on multiple projects where some use Maven and others use Gradle. We can place the Maven Toolchain specification file in our Maven home directory. This is also the default place where Gradle will look, but we can use a project property to override this location.
Continue reading →
Spring Boot 3 requires at least Java 17, but that also means the Java version used by Gradle must also be at least 17. Otherwise we will get the following error message when we build our Spring Boot project in IntelliJ using Gradle:
The issue is that the Spring Boot Gradle plugin 3.1.5 requires Java 17, but our project is using Java 11. We can fix this by explicitly setting the Java version that Gradle uses in IntelliJ. Go to Settings > Build, Execution, Deployment > Build Tools > Gradle and change the JVM used for Gradle to a JDK version of at least version 17.
Continue reading →
Sometimes we want to send HTTP requests to servers that use HTTPS with self-signed certificates.
We then need to tell HTTP Client to not check the certificate of the server.
This is like running the curl command with the --insecure
or '-k' flag.
To disable the certificate verification for HTTP Client we need to adjust the http-client.private.env.json
file.
For the environment we want to disable the certificate verification we must add a SSLConfiguration
section.
In the SSLConfiguration
section we add the verifyHostCertificate
property with value 'true'.
Continue reading →