Junit SpringAOP-@切入点:@测试方法的@Before建议不起作用

Junit SpringAOP-@切入点:@测试方法的@Before建议不起作用,junit,aop,aspectj,spring-aop,Junit,Aop,Aspectj,Spring Aop,我的工作对象是: Spring框架4.3.2 AspectJ 1.8.9 朱尼特 格拉德尔 该项目基于多个模块 在src/main/java(main)中,我有一些@Aspect类,它们按照预期的方式工作。我可以通过运行时和测试来确认它 现在我需要JUnit通过日志显示执行的@Test方法名 因此,在src/test/java(test)中,我有以下内容: class TestPointcut { @Pointcut("execution(@org.junit.Test * *()

我的工作对象是:

  • Spring框架4.3.2
  • AspectJ 1.8.9
  • 朱尼特
  • 格拉德尔
该项目基于多个模块

src/main/java
(main)中,我有一些
@Aspect
类,它们按照预期的方式工作。我可以通过运行时和测试来确认它

现在我需要JUnit通过日志显示执行的
@Test
方法名

因此,在
src/test/java
(test)中,我有以下内容:

class TestPointcut {

    @Pointcut("execution(@org.junit.Test * *())")                         
    public void testPointcut(){}

}

@Aspect
@Component
public class TestAspect {

    private static final Logger logger = LoggerFactory.getLogger(TestAspect.class.getSimpleName());

    @Before(value="TestPointcut.testPointcut()")
    public void beforeAdviceTest(JoinPoint joinPoint){
        logger.info("beforeAdviceTest - Test: {} - @Test: {}", joinPoint.getTarget().getClass().getName(), joinPoint.getSignature().getName() );
    }

}
观察第二个类有
@方面
@组件
,因此它被Spring识别

注意:我可以确认,如果我写错了
@Pointcut
语法或表达式,我会出错

问题是当我执行我的
@Test
方法时,对于
testspect
类,
@Before
建议永远不起作用

我在谷歌做了一项研究,发现
@Pointcut(“execution(@org.junit.Test**())”)
模式是正确的。 即使我使用更明确的方法,例如:
@Pointcut(value=“execution(public void com.manuel.jordan.controller.persona.*Test.*Test())”
,它也不起作用

考虑到我对
Gradle

project(':web-27-rest') {
    description 'Web - Rest'
    dependencies {
       compile project(':web-27-service-api')

       testRuntime project(':web-27-aop')
       testRuntime project(':web-27-aop').sourceSets.test.output
有什么遗漏或错误

阿尔法

一种测试类别是:

  • 服务器端使用
    @参数
    @ClassRule
    +
    @Rule
因此:

@RunWith(Parameterized.class)
@ContextConfiguration(classes={RootApplicationContext.class})
@Transactional
public class PersonaServiceImplTest {

    @ClassRule
    public static final SpringClassRule SPRING_CLASS_RULE= new SpringClassRule();

    @Rule
    public final SpringMethodRule springMethodRule = new SpringMethodRule();

    @Autowired
    private PersonaService personaServiceImpl;

    ...

    @Parameters
    public static Collection<Persona[]> data() {
     .....
        });
    }

    ...

    @Test
    @Sql(scripts={"classpath:....-script.sql"})
    public void saveOneTest(){
    ....
    }

您可以使用AspectJ编译或加载时编织作为SpringAOP代理的替代方案。在这种方法中,您将不会依赖spring上下文复杂的逻辑在代码中应用建议。方面代码将在编译或类加载阶段内联。 下面的示例显示了如何启用AspectJ编译时编织:

pom.xml

此Maven配置启用AspectJ编译器,对类进行字节码后处理


org.aspectj
aspectjrt
org.codehaus.mojo
aspectj maven插件
1.6
真的
${java.source}
${java.target}
${java.target}
UTF-8
假的
假的
aspectj编译
编译
aspectj编译测试
测试编译
org.aspectj
aspectjrt
${aspectj.version}
org.aspectj
aspectjtools
${aspectj.version}
applicationContext.xml

此外,您可能需要将方面实例添加到Spring应用程序上下文中以进行依赖项注入


JUnit实例化您的测试类。因此,Spring没有参与,因此无法将AOP建议应用于测试实例

正如Sergey Bespalov所提到的,将AspectJ建议应用于测试实例的唯一方法是使用编译时或加载时编织。请注意,这不会在Spring中配置。Spring可用于为Spring管理的Bean配置AOP,但测试实例由测试框架管理(即,您的场景中的JUnit4)

但是,对于使用SpringTestContext框架的测试,我不建议使用AspectJ。相反,最好的解决方案是实现执行日志记录的自定义
TestExecutionListener
。然后,您可以通过
@TestExecutionListeners
显式注册该
TestExecutionListener
,或者让它为您的整个套件自动拾取。对于后者,请参阅《弹簧参考手册》测试章节中关于自动发现的讨论

问候,


Sam(SpringTestContext框架的作者)

您能在这里提供您的测试类代码吗?Hello@SergeyBespalov代码已更新,请参阅
Alpha
部分。谢谢您可以尝试为测试类添加
@EnableAspectJAutoProxy(proxyTargetClass=true)
注释。您好@SergeyBespalov,它不起作用。似乎“遗漏”了其他东西您正在使用哪种编织?是spring aop代理吗?非常有趣,想知道
Gradle
的等价物是什么。让我做一个研究。你好,谢尔盖,考虑山姆的回答。也非常感谢您的宝贵支持。Sam的回答解释了这个问题,但奇怪的是为什么测试实例不是ApplicationContext的一部分。我想这可能是个虫子。我建议您尝试AspectJ编译器,它将解决您在站点上询问的这个和其他AOP问题。我在我所有的项目中都使用它,可以说它很好。是的,
但奇怪的是为什么测试实例不是ApplicationContext的一部分,我也感到困惑,但在做了一个分析之后:我认为这不是一个bug,因为即使您看到带有一组Spring注释的测试类,它也不包含
@配置,
@组件
@服务
等。因此,它既不是Spring创建的,也不是Spring处理的。它由JUnit创建,然后由于测试类中声明的当前注释,一些bean“可用”。通过Sam的建议,我完成了我的方法。我建议您尝试AspectJ编译器,它将解决您在网站上询问的AOP问题,让我们看看。但是我已经确认其中一个是一种bug,我已经在另一篇文章中给你写了一条关于JIRA的评论。不确定,但你能帮我一把吗?谢谢你的宝贵解释,山姆。我会研究一下你的建议。关于中的JUnit
@Transactional
@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={RootApplicationContext.class, ServletApplicationContext.class})
public class PersonaDeleteOneControllerTest {

    @Autowired
    private WebApplicationContext webApplicationContext;

    private MockMvc mockMvc;

    private ResultActions resultActions;

    ...

    @BeforeClass
    public static void setUp_(){
      ...
    }

    @Before
    public void setUp(){
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    }

    @Test
    public void deleteOneHtmlGetTest() throws Exception {