This article will focus on JUnit 5, but most of the things should be applicable for any other testing framework, your imagination is the only limit.
JUnit5 File and code templates
IntelliJ IDEA allows creating test classes with the following shortcut (Ctrl + Shift + T / ⇧ + ⌘ + T). This window allows specifying the test framework, name, package and also can generate test functions.
The templates which are used for the test classes are defined in the File and Code templates inside the IDE settings.
JUnit5 Test class
This file by itself is sufficient, but it is a good place to add imports which are present in all test classes like assertions, mocks etc.
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test
#parse("File Header.java")
class ${NAME} {
${BODY}
}
Remember to enable the Live Template otherwise it won’t work.
JUnit5 setUp method
Most of the time the setUp method assigns the class under test to a property which is then used by all test functions. I like to use the following template which streamlined the property assignment with the help of IntelliJ IDEA suggestions.
@org.junit.jupiter.api.BeforeEach
void setUp() {
systemUnderTest = ${CLASS_NAME}()
}
Live templates
Live templates are a little different from File and Code templates because they can be used when writing code. Templates are applicable only in a defined context, this context prevents namespace pollution. For example: adding a Kotlin function inside a Groovy Gradle file would make no sense.
All the templates, abbreviations and descriptions can be modified to suite a different need.
Adding Gradle dependencies
All tests need some libraries to make testing easier however adding them to the build.gradle mostly consists of copying and pasting them. To help with this, a live template can be used for adding dependencies which are always used together. Please take note of the Applicable context in the bottom left of the modal.
Abbreviation: depsTest
Description: Testing dependencies
Creating a test function
My most used and simplest live template.
Abbreviation: test
Description: A JUnit5 test
@org.junit.jupiter.api.Test
fun `$NAME$`() {
$END$
}
The variables used are pretty self-explanatory, however instead of $BODY$ I used the $END$ variable. For me using the $END$ is better because it correctly places the cursor after completing the live template. When I used the $BODY$ variable, most of the time I couldn’t think of a test body straight away, so I pressed enter on an empty $BODY$ and then manually navigated the cursor.
All the following live templates also use the Kotlin: class context.
Creating a nested test class
Sometimes test functions can be grouped into a cohesive nested test class. This template can be nicely chained with the test function template.
Abbreviation: nested
Description: A Nested Junit5 class
@org.junit.jupiter.api.Nested
inner class $NAME$ {
$END$
}
Create a parameterized enum test
Parameterized help with reducing the number of tests functions when their set-up can be put into variables e.g a converter input. If the variable is an enum class then the following live template can be used.
Abbreviation: paramEnum
Description: A parameterized EnumSource JUnit5 test
@org.junit.jupiter.params.ParameterizedTest
@org.junit.jupiter.params.provider.EnumSource($CLASS$::class)
fun `$NAME$`($CLASS_NAME$: $CLASS$) {
$END$
}
This template uses the edit variable modal in order to specify the test function parameter. The camelCase function inside the expression column works just like the name suggests. Most of the time the parameter name will be the same as the class name, but it is possible to change it during creation.
Create a parameterized test with an arguments provider
For me tests which use parameters from an ArgumentsSource always require the most boilerplate upfront. This live template is much more complicated than the previous ones, but it cuts down the boilerplate significantly.
Abbreviation: paramProvider
Description: A parameterized ArgumentsSource JUnit5 test
@org.junit.jupiter.params.ParameterizedTest
@org.junit.jupiter.params.provider.ArgumentsSource($CLASS$::class)
fun `$NAME$`($PARAMS$) {
$BODY$
}
class $CLASS$ : ArgumentsProvider {
override fun provideArguments(context: ExtensionContext?): Stream<out Arguments> {
return Stream.of(
testCase($END$),
)
}
private fun testCase($PARAMS$) =
Arguments.of()
}
The testCase function allows the use of named arguments when creating a “test case”.
Summary
Testing involves some boilerplate but luckily modern tools can help with reducing them. These templates are by no means exhaustive, but I hope they give an idea of what can be achieved with them.
If you’re interested in more things that IntelliJ IDEA is capable of feel free to check out my blog post about my most used IDE features.
https://akjaw.com/17-intellij-ide-features-for-faster-development/