文档章节

Spring、Spring Boot和TestNG测试指南 - 测试AOP

jarchan
 jarchan
发布于 2017/09/07 13:06
字数 679
阅读 66
收藏 0

码云地址

Spring提供了一套AOP工具,但是当你把各种Aspect写完之后,如何确定这些Aspect都正确的应用到目标Bean上了呢?本章将举例说明如何对Spring AOP做测试。

首先先来看我们事先定义的Bean以及Aspect。

FooServiceImpl

@Component
public class FooServiceImpl implements FooService {

  private int count;

  @Override
  public int incrementAndGet() {
    count++;
    return count;
  }

}

FooAspect

@Component
@Aspect
public class FooAspect {

  @Pointcut("execution(* me.chanjar.aop.service.FooServiceImpl.incrementAndGet())")
  public void pointcut() {
  }

  @Around("pointcut()")
  public int changeIncrementAndGet(ProceedingJoinPoint pjp) {
    return 0;
  }

}

可以看到FooAspect会修改FooServiceImpl.incrementAndGet方法的返回值,使其返回0。

例子1:测试FooService的行为

最简单的测试方法就是直接调用FooServiceImpl.incrementAndGet,看看它是否使用返回0。

SpringAop_1_Test

@ContextConfiguration(classes = { SpringAopTest.class, AopConfig.class })
public class SpringAop_1_Test extends AbstractTestNGSpringContextTests {

  @Autowired
  private FooService fooService;

  @Test
  public void testFooService() {

    assertNotEquals(fooService.getClass(), FooServiceImpl.class);

    assertTrue(AopUtils.isAopProxy(fooService));
    assertTrue(AopUtils.isCglibProxy(fooService));

    assertEquals(AopProxyUtils.ultimateTargetClass(fooService), FooServiceImpl.class);

    assertEquals(AopTestUtils.getTargetObject(fooService).getClass(), FooServiceImpl.class);
    assertEquals(AopTestUtils.getUltimateTargetObject(fooService).getClass(), FooServiceImpl.class);

    assertEquals(fooService.incrementAndGet(), 0);
    assertEquals(fooService.incrementAndGet(), 0);

  }

}

先看这段代码:

assertNotEquals(fooService.getClass(), FooServiceImpl.class);

assertTrue(AopUtils.isAopProxy(fooService));
assertTrue(AopUtils.isCglibProxy(fooService));

assertEquals(AopProxyUtils.ultimateTargetClass(fooService), FooServiceImpl.class);

assertEquals(AopTestUtils.getTargetObject(fooService).getClass(), FooServiceImpl.class);
assertEquals(AopTestUtils.getUltimateTargetObject(fooService).getClass(), FooServiceImpl.class);

这些是利用Spring提供的AopUtilsAopTestUtilsAopProxyUtils来判断FooServiceImpl Bean是否被代理了(Spring AOP的实现是通过动态代理来做的)。

但是证明FooServiceImpl Bean被代理并不意味着FooAspect生效了(假设此时有多个@Aspect),那么我们还需要验证FooServiceImpl.incrementAndGet的行为:

assertEquals(fooService.incrementAndGet(), 0);
assertEquals(fooService.incrementAndGet(), 0);

例子2:测试FooAspect的行为

但是总有一些时候我们是无法通过例子1的方法来测试Bean是否被正确的advised的:

  1. advised方法没有返回值
  2. Aspect不会修改advised方法的返回值(比如:做日志)

那么这个时候怎么测试呢?此时我们就需要用到Mockito的Spy方法结合Spring Testing工具来测试。

SpringAop_2_Test

@ContextConfiguration(classes = { SpringAop_2_Test.class, AopConfig.class })
@TestExecutionListeners(listeners = MockitoTestExecutionListener.class)
public class SpringAop_2_Test extends AbstractTestNGSpringContextTests {

  @SpyBean
  private FooAspect fooAspect;

  @Autowired
  private FooService fooService;

  @Test
  public void testFooService() {

    // ...
    verify(fooAspect, times(2)).changeIncrementAndGet(any());

  }

}

这段代码和例子1有三点区别:

  1. 启用了MockitoTestExecutionListener,这样能够开启Mockito的支持(回顾一下Chapter 3: 使用Mockito
  2. @SpyBean private FooAspect fooAspect,这样能够声明一个被Mockito.spy过的Bean
  3. verify(fooAspect, times(2)).changeIncrementAndGet(any()),使用Mockito测试FooAspect.changeIncrementAndGet是否被调用了两次

上面的测试代码测试的是FooAspect的行为,而不是FooServiceImpl的行为,这种测试方法更为通用。

例子3:Spring Boot的例子

上面两个例子使用的是Spring Testing工具,下面举例Spring Boot Testing工具如何测AOP(其实大同小异):

SpringBootAopTest

@SpringBootTest(classes = { SpringBootAopTest.class, AopConfig.class })
@TestExecutionListeners(listeners = MockitoTestExecutionListener.class)
public class SpringBootAopTest extends AbstractTestNGSpringContextTests {

  @SpyBean
  private FooAspect fooAspect;

  @Autowired
  private FooService fooService;

  @Test
  public void testFooService() {

    // ...
    verify(fooAspect, times(2)).changeIncrementAndGet(any());

  }

}

参考文档

© 著作权归作者所有

共有 人打赏支持
jarchan

jarchan

粉丝 60
博文 11
码字总数 8798
作品 2
崇明
技术主管
私信 提问
Spring Boot 和 testNG 和 eclipse背景色

通过之前的博文,我们已经验证,Spring环境下完成access数据访问没有问题。下面我们直接在Spring环境下部署我们的升级项目。 1.导入Spring Boot Spring Boot是Spring的子项目,用来解决项目配...

pandamonica
2017/09/19
0
0
eclipse上cxf与testNG的冲突

我打算在eclipse上的一个maven项目的某一个类发布,成为web service,打算使用cxf进行发布。 最初这个测试用的maven项目是这样的: 也就是说,在导入cxf之前,这个maven项目的功能是可以正常...

pandamonica
09/07
0
0
Spring Framework体系结构简介

说明:以下转自Spring官方文档,用的版本为4.3.11版本。 一、引用官方文档 所述核心容器由以下部分组成, ,,,和(弹簧表达式语言)模块。 的和模块提供框架的基本零件,包括IOC和依赖注入...

easonjim
2017/09/16
0
0
An internal error occurred during: "Building UI model". com/google/common/base/Function

版权声明:本文为 testcsdn(微wx笑) 原创文章,非商用自由转载-保持署名-注明出处,谢谢。 https://blog.csdn.net/testcsdn/article/details/78798610 An internal error occurred during: "...

微wx笑
2017/12/14
0
0
25 extentreports/allure美化测试报告

最近好多在微信问关于测试报告生成问题。其实TestNG执行结果就已经自带了测试报告,只是比较丑。 这里我就顺便推荐下另外的两种Report,但是文档我就不细写了,只大概写下用法。 extentrepo...

米阳MeYoung
08/07
0
0

没有更多内容

加载失败,请刷新页面

加载更多

node上的redis调用优化示例

Node.js读写数据到influxDB,目前已经有一个库node-influx, 这个库功能非常强大,但是我个人使用这个库的时候,遇到无法解决的问题。 使用curl都可以写数据到influxDB,但是用node-influx总是...

前端攻城老湿
23分钟前
1
0
The setting logImpl is not known

问题: org.apache.ibatis.builder.BuilderException: The setting logImpl is not known. Make sure you spelled it correctly (case sensitive). MyBatis 3.1.1 -jar还没有 logImpl 这个设......

晨猫
35分钟前
1
0
eslint一些规则

一、指定js文件不使用 ESLint 语法检查 1.整个文件范围内禁止规则出现警告 将/* eslint-disable */放置于文件最顶部 /* eslint-disable */alert('foo'); 2.在文件中临时禁止规则出现警告 ...

xiaoge2016
35分钟前
1
0
mac终端常用命令

ls ls,list的简写,列出目录的内容。 -a:显示隐藏文件 -l:以列表方式显示文件信息 -h:配合-l,显示更人性化 配合通配符使用 ls *.txt:显示所有以.txt结尾的文件 ls ?.txt:显示‘任意字符.tx...

xiaobai1315
37分钟前
1
0
java命令行读取配置,和加载jar的方式

--spring.profiles.active=t2,t3,xextest --spring.profiles.include=quartz-jp-Djava.ext.dirs=libs-Dspring.config.location=/data/apps/DBconfig -cp  "config/*"  start.sh......

经常把天聊死的胖子
49分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部