JUnit tests for AspectJ



我正在尝试为自定义方面编写JUNIT测试。这是方面类摘要:

@Aspect
@Component
public class SampleAspect {
    private static Logger log = LoggerFactory.getLogger(SampleAspect.class);
    @Around("execution(* org.springframework.data.mongodb.core.MongoOperations.*(..)) || execution(* org.springframework.web.client.RestOperations.*(..))")
    public Object intercept(final ProceedingJoinPoint point) throws Throwable {
        logger.info("invoked Cutom aspect");
         return point.proceed();
    }
}

因此,每当关节点匹配尖端时,上面的方面都会截获。它的工作正常。

但是我的问题是如何对该类进行单位测试。我有以下Junit测试:

@Test(expected = MongoTimeoutException.class)
    public void TestWithMongoTemplate() {
        //MongoDocument class
        TestDocument test = new TestDocument();
        ApplicationContext ctx = new AnnotationConfigApplicationContext(TestMongoConfigurationMain.class);
        MongoTemplate mongoTemplate = ctx.getBean(MongoTemplate.class);
        //this call is being intercepted by SampleAspect
        mongoTemplate.save(test);
    }

因此,我的mongoTemplate.save(test)在JUNIT中被SampleAspect截获,因为它与PointCut匹配。但是,我应该如何确保在Junits(可能是通过断言)我的SampleAspect何时调用该关节点?

我不能从 intercept()上断言返回值,因为除了执行关节点外,它没有其他特殊作用。因此,无论我的少年是通过返回值执行的,无论是通过方面执行还是定期执行。

如果提供,任何方面测试的代码片段都将很棒。谢谢

我认为您要测试的是织造和尖端匹配的方面。请注意,这将是集成而不是单位测试。如果您真的想单元测试您的方面逻辑,并且由于您已经通过" Mockito"标记了该问题,我建议您做到这一点:编写单元测试并模拟该方面的JoinPoint,也许还有其他参数(如果有)。这是一个稍微复杂的示例,其中有一些内在的逻辑:

Java类是由方面来定位的:

package de.scrum_master.app;
public class Application {
    public static void main(String[] args) {
        new Application().doSomething(11);
        new Application().doSomething(-22);
        new Application().doSomething(333);
    }
    public void doSomething(int number) {
        System.out.println("Doing something with number " + number);
    }
}

测试中的方面:

package de.scrum_master.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class SampleAspect {
    @Around("execution(* doSomething(int)) && args(number)")
    public Object intercept(final ProceedingJoinPoint thisJoinPoint, int number) throws Throwable {
        System.out.println(thisJoinPoint + " -> " + number);
        if (number < 0)
            return thisJoinPoint.proceed(new Object[] { -number });
        if (number > 99)
            throw new RuntimeException("oops");
        return thisJoinPoint.proceed();
    }
}

运行Application.main(..)时的控制台日志:

您可以看到,该方面在11上传递,否定-22并给予333的例外:

execution(void de.scrum_master.app.Application.doSomething(int)) -> 11
Doing something with number 11
execution(void de.scrum_master.app.Application.doSomething(int)) -> -22
Doing something with number 22
execution(void de.scrum_master.app.Application.doSomething(int)) -> 333
Exception in thread "main" java.lang.RuntimeException: oops
    at de.scrum_master.aspect.SampleAspect.intercept(SampleAspect.aj:15)
    at de.scrum_master.app.Application.doSomething(Application.java:10)
    at de.scrum_master.app.Application.main(Application.java:7)

方面的单元测试:

现在,我们真的想验证该方面应执行应有的作用并涵盖所有执行路径:

package de.scrum_master.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import static org.mockito.Mockito.*;
public class SampleAspectTest {
    @Rule
    public MockitoRule mockitoRule = MockitoJUnit.rule();
    @Mock
    private ProceedingJoinPoint proceedingJoinPoint;
    private SampleAspect sampleAspect = new SampleAspect();
    @Test
    public void testPositiveSmallNumber() throws Throwable {
        sampleAspect.intercept(proceedingJoinPoint, 11);
        // 'proceed()' is called exactly once
        verify(proceedingJoinPoint, times(1)).proceed();
        // 'proceed(Object[])' is never called
        verify(proceedingJoinPoint, never()).proceed(null);
    }
    @Test
    public void testNegativeNumber() throws Throwable {
        sampleAspect.intercept(proceedingJoinPoint, -22);
        // 'proceed()' is never called
        verify(proceedingJoinPoint, never()).proceed();
        // 'proceed(Object[])' is called exactly once
        verify(proceedingJoinPoint, times(1)).proceed(new Object[] { 22 });
    }
    @Test(expected = RuntimeException.class)
    public void testPositiveLargeNumber() throws Throwable {
        sampleAspect.intercept(proceedingJoinPoint, 333);
    }
}

现在,运行此简单的Junit Mockito测试,以隔离地测试方面逻辑,接线/编织逻辑。对于后者,您需要另一种类型的测试。

P.S。:仅适合您,我使用了Junit和Mockito。通常,我只使用Spock及其内置的模拟功能。;-)

相关内容

  • 没有找到相关文章

最新更新