A custom annotation in Spring Boot tests is an easy and flexible way to provide the required configuration. We can use it to efficiently group all the annotations and configuration classes that we would otherwise apply to each test class separately.
As an example for this article, I’m going to create a custom annotation to configure controller tests. If you want to recreate the work described below, you will need a Spring Boot project with a REST controller and some MVC tests.
Why use a custom annotation in Spring Boot tests
One reason is to simply group all the annotations we need to apply across multiple test classes into convenient metadata. Moreover, it’s also useful when you use
@Import to register additional components required for configuring the “slice” of the system to test, as it reduces a lot of copy-and-paste code.
Another possible solution would be to create a base class and making each test extend it. However, inheritance comes with a lot of issues that I don’t want to deal with just to provide a common configuration for some tests.
A custom annotation that encloses all the common configurations for tests is both an elegant and simple solution. In the following example, instead of annotating my tests with
@Import, I’m going to create
@RestControllerIntegrationTest which will take care of all the configuration details. Thanks to this, I will avoid duplicating the code or complicating it with unnecessary inheritance.
Create a custom annotation for MVC tests
First, I’m going to replace the
@WebMvcTest annotation with a custom one. I’m going to create the following
Let’s take a look at the annotations I’m using here:
- @Retention – specifies how long an annotation is to be retained. The RUNTIME Retention Policy enables the annotation to be retained by the VM at run time.
- @Target – puts constrains on the usage of the annotation. The TYPE Element Type will allow using it on my test classes.
- @WebMvcTest – since I am creating my own annotation for MVC tests, i need to include this Spring Boot annotation to still benefit from all the default features.
Thus, I can now replace
@RestControllerIntegrationTest and still have the same functionality:
Now, I can add any additional configuration my test “slice” requires to the custom annotation.
Provide additional configuration
In my example project, I’m using the
@PreAuthorize annotation to restrict user access to the API endpoints. Therefore, I need to enable method-level security. Without it, the following test fails because it is missing the configuration required to apply the appropriate access control:
For that reason, I’m going to create a configuration class and annotate it with @EnableMethodSecurity:
Next, I’ll load it into
ApplicationContext using @ContextConfiguration in my custom annotation:
As a result, all tests in classes annotated with
@RestControllerIntegrationTest will be able to use method-level security. The following screenshot shows that my tests are passing now:
Read more about setting up tests in Spring Boot
- Spring Boot test slices with custom annotations
- Document how to use this if Keycloak is on the classpath
- My other posts regarding testing