admin管理员组

文章数量:1241125

I'm using spring-boot 3.4.2.

I want to use AOP aspects in order to modify annotations that I use in a spring boot test.

However my @Around method is not triggered during test execution. If I annotate e.g. an endpoint method inside a rest controller, than it is triggered. But I want to use it for tests.

Here's my annotation:

@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
}

Here's my Aspect:

@Aspect
@Component
public class TestAspect {
    public TestAspect() {
        // this is called - so @Component works
        System.out.println("aspect constructor called");
    }
    
    @Around("@annotation(TestAnnotation)")
    public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
        // this is NOT called in the test - @Around did not work
        System.out.println("aroundAdvice() called");
        return joinPoint.proceed();
    }
}

And here's my test:

@SpringBootTest
@ComponentScan(basePackages = { "de.mycompany" }) // root of all my packages
@TestPropertySource(value = "classpath:application-test.yml", factory = YamlPropertySourceFactory.class)
@AutoConfigureMockMvc
class MyTestClass {
    
    @Autowired
    private MockMvc mockMvc;
    
    @Test
    @TestAnnotation
    void testSomething() throws Exception {
        System.out.println("testSomething() called.");
        // test something with mockMvc
    }
}

If I annotate an endpoint in a RestController, aroundAdvice() will be triggered, whenever that endpoint is called or tested. But I need it to be triggered when my test method (here: testSomething()) is called. And that does not work.

Using the fully qualified class in @Around doesn't work either: @Around("@annotation(de.mycompany.annotation.TestAnnotation)")

I'm using spring-boot 3.4.2.

I want to use AOP aspects in order to modify annotations that I use in a spring boot test.

However my @Around method is not triggered during test execution. If I annotate e.g. an endpoint method inside a rest controller, than it is triggered. But I want to use it for tests.

Here's my annotation:

@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
}

Here's my Aspect:

@Aspect
@Component
public class TestAspect {
    public TestAspect() {
        // this is called - so @Component works
        System.out.println("aspect constructor called");
    }
    
    @Around("@annotation(TestAnnotation)")
    public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
        // this is NOT called in the test - @Around did not work
        System.out.println("aroundAdvice() called");
        return joinPoint.proceed();
    }
}

And here's my test:

@SpringBootTest
@ComponentScan(basePackages = { "de.mycompany" }) // root of all my packages
@TestPropertySource(value = "classpath:application-test.yml", factory = YamlPropertySourceFactory.class)
@AutoConfigureMockMvc
class MyTestClass {
    
    @Autowired
    private MockMvc mockMvc;
    
    @Test
    @TestAnnotation
    void testSomething() throws Exception {
        System.out.println("testSomething() called.");
        // test something with mockMvc
    }
}

If I annotate an endpoint in a RestController, aroundAdvice() will be triggered, whenever that endpoint is called or tested. But I need it to be triggered when my test method (here: testSomething()) is called. And that does not work.

Using the fully qualified class in @Around doesn't work either: @Around("@annotation(de.mycompany.annotation.TestAnnotation)")

Share Improve this question asked 2 days ago trujtruj 133 bronze badges New contributor truj is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct. 1
  • AOP works for spring managed beans the test isn't spring managed. If you want that to work you will need to setup load- or compile timeweaving instead of using proxies (the default). – M. Deinum Commented 2 days ago
Add a comment  | 

1 Answer 1

Reset to default 0

Annotations only work on beans. They work by creating proxy. Your MyTestClass is not real Spring bean.

One way to implement what you want is to implement extension and check for annotation in InvocationInterceptor.

public class MyExtension implements InvocationInterceptor {
    public void interceptTestMethod(Invocation<Void> invocation, ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext) throws Throwable {
        doMyStuff(invocationContext);
        invocation.proceed();
    }

    public <T> T interceptTestFactoryMethod(Invocation<T> invocation, ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext) throws Throwable {
        doMyStuff(invocationContext);
        return invocation.proceed();
    }

    public void interceptTestTemplateMethod(Invocation<Void> invocation, ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext) throws Throwable {
        doMyStuff(invocationContext);
        invocation.proceed();
    }

    void doMyStuff(ReflectiveInvocationContext<Method> invocationContext) {
        Method m = invocationContext.getExecutable();
        TestAnnotation a = m.getAnnotation(TestAnnotation .class);
        if(a != null){
            System.out.println("Here we go");
        }
    }
}

Put that extension on your test by adding @ExtendWith(MyExtension.class) to your test class.

本文标签: javaAOP Aspect not triggered in SpringBootTestStack Overflow