Spring、Spring Boot和TestNG测试指南 ( 7 )

发表于:2017-12-19 10:59

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:chanjarster    来源:ImportNew

  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提供的AopUtils、AopTestUtils和AopProxyUtils来判断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());
}
}
相关文章

上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号