java 未通过单元测试执行的 AspectJ 建议

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16971819/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-01 00:35:31  来源:igfitidea点击:

AspectJ advice not being executed through unit test

javaspringmavenaspectj

提问by Emilie

I'm stumped. I'm trying to test an AspectJ class. My Aspect class gets picked up perfectly when I'm running my application. However, I seem to be unable to get any Aspect class to intercept any method within a test.

我难住了。我正在尝试测试 AspectJ 类。当我运行我的应用程序时,我的 Aspect 类得到了完美的选择。但是,我似乎无法获得任何 Aspect 类来拦截测试中的任何方法。

I am using Spring 3.2.2, AspectJ 1.7.2 and Maven 4.

我使用的是 Spring 3.2.2、AspectJ 1.7.2 和 Maven 4。

Here is the simple test I'm working with:

这是我正在使用的简单测试:

The Test AspectJ class

测试 AspectJ 类

package my.package.path.config;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Aspect
public class TestAOP {
    private String message;

    public TestAOP() {
    }

    @Pointcut("execution(* my.package.path.TestAOPClient.relayMessage(..))")
    public void aopPointcut() {
    }

    @Around("aopPointcut()")
    public String monitor(ProceedingJoinPoint pjp) throws Throwable {
        String msg = (String)pjp.proceed();
        this.setMessage(msg);
        return msg;
    }

}

}

The class whose method is being intercepted

方法被拦截的类

package my.package.path.config;

public class TestAOPClient {
    public String relayMessage(String msg) {
        return msg;
    }
}

The Test Class

测试班

package my.package.path.config;

import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;

@Configuration
@ContextConfiguration(classes={WebConfig.class})
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration("src/main/java")
public class AopConfigTest extends AbstractJUnit4SpringContextTests {

     @Bean
     public TestAOP testAop() throws Exception {
        return new TestAOP();
     }

     @Test
     public void assertTestConfigIsActive() {
        TestAOPClient client = new TestAOPClient();
        client.relayMessage("hello");
        assertThat(((TestAOP)applicationContext.getBean("testAop")).getMessage(), equalTo("hello"));

    }
}

The WebConfig file

网络配置文件

package my.package.path.web.context;
@Configuration
@EnableWebMvc
@EnableAspectJAutoProxy(proxyTargetClass=false)
@ComponentScan(value={"my.package.path.config", "my.package.path.web"})
public class WebConfig {

}

Invariably, I will get the assertion error

总是,我会得到断言错误

 Expected: "hello" but: was null

My WebApplicationContext seems to be picked up, since at runtime, I will get an ApplicationContext failed to load error if I specify a class that does not exist for my Aspect pointcut.

我的 WebApplicationContext 似乎被选中了,因为在运行时,如果我为我的 Aspect 切入点指定一个不存在的类,我将收到 ApplicationContext failed to load 错误。

What am I missing?

我错过了什么?

采纳答案by Pavel Horal

It is kind of strange that you are using your unit test also as a @Configurationsource.

您还使用单元测试作为@Configuration源,这有点奇怪。

You should remove the @Configurationannotation from the unit test and move the testAOP()bean definition to WebConfig. But most importantly the bean being advised must not be created manually, but by Spring:

您应该@Configuration从单元测试中删除注释并将testAOP()bean 定义移动到WebConfig. 但最重要的是,被建议的 bean不能手动创建,而是由 Spring 创建

@ContextConfiguration(classes={WebConfig.class})
@WebAppConfiguration("src/main/java")
public class AopConfigTest extends AbstractJUnit4SpringContextTests {

     @Autowired
     private TestAOP testAop;

     @Autowired
     private TestAOPClient client;

     @Test
     public void assertTestConfigIsActive() {
        client.relayMessage("hello");
        assertThat(((TestAOP)applicationContext.getBean("testAop")).getMessage(), 
            equalTo("hello"));
    }

}

Updated config with the bean definition:

使用 bean 定义更新配置:

@Configuration
@EnableWebMvc
@EnableAspectJAutoProxy(proxyTargetClass=false)
@ComponentScan(value={"my.package.path.config", "my.package.path.web"})
public class WebConfig {

    @Bean
    public TestAOP testAop() throws Exception {
        return new TestAOP();
    }

    @Bean
    public TestAOPClient testAopClient() throws Exception {
        return new TestAOPClient();
    }

}

If your target was to test whether the AOP configuration works and TestAOPis really a testing bean (not just a dummy name for this question), you can create a special TestConfigconfiguration class, move the bean definition there and use it from the test @ContextConfiguration(classes={WebConfig.class,TestConfig.class}).

如果您的目标是测试 AOP 配置是否有效并且TestAOP确实是一个测试 bean(不仅仅是这个问题的虚拟名称),您可以创建一个特殊的TestConfig配置类,将 bean 定义移到那里并从 test 中使用它@ContextConfiguration(classes={WebConfig.class,TestConfig.class})

回答by Franti?ek Hartman

Your pointcut configuration is wrong (package should be my.package.path.config to match your test client)

您的切入点配置错误(包应该是 my.package.path.config 以匹配您的测试客户端)

@Pointcut("execution(* my.package.path.TestAOPClient.relayMessage(..))")

and your client is

你的客户是

package my.package.path.config;

public class TestAOPClient {
...

change it to this

改成这个

@Pointcut("execution(* my.package.path.config.TestAOPClient.relayMessage(..))")

should work.

应该管用。