Create a custom annotation to configure Spring Boot tests

featured image

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.

Prerequisites

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 @WebMvcTest and @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 RestControllerIntegrationTest annotation:

Let’s take a look at the annotations I’m using here:

  1. @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.
  2. @Target – puts constrains on the usage of the annotation. The TYPE Element Type will allow using it on my test classes.
  3. @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 @WebMvcTest with @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:

Spring test failing without annotation

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:

Verify results

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:

passing tests with custom annotation

Read more about setting up tests in Spring Boot

Photo by Georgia Maciel from Pexels

Leave a Reply

Your email address will not be published.