Search code examples
spring-bootannotationsspring-boot-testmockmvcmeta-annotation

property mockMvc has not been initialized when I use my custom meta-annotaion


For each controller I have following test class:

@WebMvcTest(controllers = [MyFirstController::class])
@AutoConfigureMockMvc(addFilters = false)
@Import(JacksonConfig::class)
class MyFirstControllerTest {
...

For another one it will be almost the same:

@WebMvcTest(controllers = [MySecondController::class])
@AutoConfigureMockMvc(addFilters = false)
@Import(JacksonConfig::class)
class MySecondControllerTest {
...

I was inspired by spring boot annotation(for example) which contains a lot of nested annotation. So I want to create annotation to replace all 3 annotations in the way like this.

@MyWebMvcTest(controllers = [MySecondController::class])
class MySecondControllerTest { 
   ...

So based on this I've created:

@WebMvcTest
@AutoConfigureMockMvc(addFilters = false)
@Import(JacksonConfig.class)
public @interface MyWebMvcTest {
    @AliasFor(annotation = WebMvcTest.class, attribute = "controllers")
    Class<?>[] value() default {};
}

and test:

@MyWebMvcTest(MyController::class)
class MyControllerTest {

But I see the error during test startup:

lateinit property mockMvc has not been initialized
kotlin.UninitializedPropertyAccessException: lateinit property mockMvc has not been initialized

Update

Thanks for Alexander Radchenko answer I've added retention policy:

@Retention(RetentionPolicy.RUNTIME)
@WebMvcTest
@AutoConfigureMockMvc(addFilters = false)
@Import(JacksonConfig.class)
public @interface MyWebMvcTest {
    @AliasFor(annotation = WebMvcTest.class, attribute = "controllers")
    Class<?>[] value() default {};
}

It definitely should be added but unfortunately it is not enough. I see the similar error.

If anyone interested in MRE(please notice the branch name ) - https://github.com/gredwhite/springboottestconfigissue_demo/tree/feature/meta-annnotation-for-test/src/test/kotlin/com/example/demo/controller


Solution

  • Your custom annotation with default retention CLASS is not available to Spring processors. You need to set RUNTIME retention:

    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyWebMvcTest {
      ...
    }
    

    Another issue is that you put MyWebMvcTest (implemented on Java) to the folder src/main/kotlin. You have 2 options:

    • move annotation to src/test/java
    • convert it to Kotlin