Spring AOP - @Pointcut:@Before对@Test方法的建议不起作用

时间:2016-09-21 14:54:57

标签: junit aop aspectj spring-aop

我正在使用:

  • Spring Framework 4.3.2
  • AspectJ 1.8.9
  • JUnit的
  • 摇篮

该项目基于多个模块。

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() );
    }

}

观察第二个班级有@Aspect@Component因此被春天认可

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

问题在于我执行@Test方法时,对于TestAspect类,@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

缺少什么或错了什么?

α

一种测试类是:

  • 服务器端使用@Parameters@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(){
    ....
    }

其他是:

  • Web端使用(@WebAppConfiguration)并且:
    • @Parameters@ClassRule + @Rule
    • 没有@Parameters@ClassRule + @Rule

因此(低于第二种方法):

@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 {

2 个答案:

答案 0 :(得分:4)

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

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

但是,对于使用 Spring TestContext Framework 的测试,我不建议使用AspectJ。相反,最佳解决方案是实现执行日志记录的自定义TestExecutionListener。然后,您可以通过TestExecutionListener明确注册@TestExecutionListeners,或者自动为整个套件选择{{1}}。对于后者,请参阅Spring参考手册“测试”一章中有关自动发现的讨论。

此致

Sam( Spring TestContext Framework的作者

答案 1 :(得分:1)

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

<强>的pom.xml

这个Maven配置使AspectJ编译器可以对你的类进行字节码后处理。

<dependencies>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjrt</artifactId>
    </dependency>
</dependencies>
<plugins>
    <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>aspectj-maven-plugin</artifactId>
        <version>1.6</version>
        <configuration>
            <showWeaveInfo>true</showWeaveInfo>
            <source>${java.source}</source>
            <target>${java.target}</target>
            <complianceLevel>${java.target}</complianceLevel>
            <encoding>UTF-8</encoding>
            <verbose>false</verbose>
            <XnoInline>false</XnoInline>
        </configuration>
        <executions>
            <execution>
                <id>aspectj-compile</id>
                <goals>
                    <goal>compile</goal>
                </goals>
            </execution>
            <execution>
                <id>aspectj-compile-test</id>
                <goals>
                    <goal>test-compile</goal>
                </goals>
            </execution>
        </executions>
        <dependencies>
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjrt</artifactId>
                <version>${aspectj.version}</version>
            </dependency>
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjtools</artifactId>
                <version>${aspectj.version}</version>
            </dependency>
        </dependencies>
    </plugin>
</plugins>

<强>的applicationContext.xml

此外,您可能需要将方面实例添加到Spring Application Context以进行依赖项注入。

<bean class="TestAspect" factory-method="aspectOf"/>