Spring、Spring Boot和TestNG测试指南 - 测试AOP
发布日期:2021-08-27 07:03:20 浏览次数:2 分类:技术文章

本文共 3595 字,大约阅读时间需要 11 分钟。

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

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

FooServiceImpl:

@Componentpublic class FooServiceImpl implements FooService {  private int count;  @Override  public int incrementAndGet() {    count++;    return count;  }}

FooAspect:

@Component@Aspectpublic 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提供的、和来判断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的支持(回顾一下)

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

参考文档

转载地址:https://blog.csdn.net/weixin_33910434/article/details/88986069 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:深入了解一个超快的 CSS 引擎: Quantum CSS (也称 Stylo) ★ Mozilla Hacks
下一篇:搭建 Jenkins-2.83 服务,部署 spring boot 项目

发表评论

最新留言

路过,博主的博客真漂亮。。
[***.116.15.85]2024年03月27日 13时15分34秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

2020word替换所有文本_Excel字符函数(5):REPLACE、SUBSTITUTE查找替换函数之区别... 2019-04-21
win10安装ipython_win10环境 ipython app.py 8080 这里为什么是ipython 这步无法启动 2019-04-21
假定在MYSQL_假定在名称为教学库的数据库中包含有学生、课程和选课三个表,它们的定义如下 - 问答库... 2019-04-21
mysql多字段存储过程_mysql 的存储过程_多字段 2019-04-21
python怎么创建字符串列表_如何在python列表中为每个字符串创建子列表? 2019-04-21
vba ado 执行多条mysql 语句_access 按钮 多条sql语句 VBA 2019-04-21
弹性方法计算连续梁板内力_(梁板结构)混凝土结构设计复习题及答案 2019-04-21
java root权限_android java获得root权限调用linux命令 | 学步园 2019-04-21
java最小化窗体_JAVA窗体最大化最小化控制+托盘 2019-04-21
java 注解 数组默认值_Java注解默认值 2019-04-21
java流程语句_Java流程控制语句 2019-04-21
java require_java正则中的requireEnd和hitEnd 2019-04-21
400错误java_java代码转化成c#代码 报400错误 2019-04-21
java常见对象_Java 常见对象 02 2019-04-21
spring java配置_Spring Java配置要点 2019-04-21
共享内存 java_java - Java客户端-服务器编程:客户端之间的共享内存 - 堆栈内存溢出... 2019-04-21
java布局管理器空布局_Java图形化界面设计——布局管理器之null布局(空布局)... 2019-04-21
java gas station_LeetCode – 774. Minimize Max Distance to Gas Station 2019-04-21
java项目无法加载到tomcat_eclipse+tomcat添加项目进来无法启动tomcat 2019-04-21
后缀树建立 java_实用算法实现-第 8 篇后缀树和后缀数组 [2 最长公共子串] 2019-04-21