SpringBoot中单元测试如何对包含AopContext.currentProxy()的方法进行测试

springboot,单元测试,如何,包含,aopcontext,currentproxy,方法,进行,测试 · 浏览次数 : 179

小编点评

**问题分析:** 在AopContext中调用自身的函数时,出现 `java.lang.IllegalStateException: Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available, and ensure that AopContext.currentProxy() is invoked in the same thread as the AOP invocation context` 错误。 **解决方案:** 1. **使用`@Mock`注解模拟`AopContext`中的静态方法:** - 创建一个`MockStatic`对象,其中包含 `currentProxy()` 方法的返回值。 - 在`@BeforeEach`方法中设置`aopContextMockedStatic`。 2. **使用`@Mock`注解模拟`OrderServiceImpl`的`insertDemo()`方法:** - 创建一个`Mock`对象,其中包含`insertDemo()`方法的行为。 - 在`@Mock`中注入`orderServiceMock`。 3. **使用`@Autowired`注解注入`OrderServiceImpl`:** - 在`@BeforeEach`方法中打开Mocks,将`orderServiceMock`注入到`aopContextMockedStatic`中。 4. **在测试方法中访问`AopContext`:** - 在测试方法中使用`aopContextMockedStatic`访问`AopContext`中的静态方法。 **示例代码:** ```java // Mock AopContext @MockStatic private MockedStatic aopContextMockedStatic; // Mock OrderServiceImpl @Mock private OrderServiceImpl orderServiceMock; // Inject OrderServiceImpl into AopContext @Autowired private AopContext aopContext; // Set 'exposeProxy' property to 'true' aopContextMockedStatic.when(AopContext::currentProxy).thenReturn(orderServiceMock); // Perform test int result = orderServiceUnderTest.insertOrder(); // Assert result assertThat(result).isEqualTo(1); ```

正文

今天在工作中遇到一个问题,一个Service类中有一个方法,其中使用了 AopContext.currentProxy() 去访问自身的函数,例如

int result = ((OrderServiceImpl) AopContext.currentProxy()).save();

单元测试方法如下:

@InjectMocks
private OrderServiceImpl orderServiceUnderTest;

@Test
@DisplayName("AopContext测试")
public void test() {
    int result = orderServiceUnderTest.insertDemo();
    assertThat(result).isEqualTo(1);
}

但是在运行测试的时候出现了 java.lang.IllegalStateException: Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available, and ensure that AopContext.currentProxy() is invoked in the same thread as the AOP invocation context.

这时候需要将AopContext的静态方法也mock,同时,需要将被测类 OrderServiceImpl 再注入一次,注入到AopContext中。

具体代码如下:

public class SpringTestDemoApplicationTests {
    @InjectMocks
    private OrderServiceImpl orderServiceUnderTest;

    @Spy
    private orderServiceImpl orderServiceMock;

    @Mock
    private MockedStatic<AopContext> aopContextMockedStatic;

    @BeforeEach
    public void setup() {
        openMocks(this);
        aopContextMockedStatic.when(AopContext::currentProxy).thenReturn(orderServiceMock);
    }

    @Test
    @DisplayName("AopContext测试")
    public void test() {
        int result = orderServiceUnderTest.insertOrder();
        assertThat(result).isEqualTo(1);
    }

    @AfterEach
    public void tearDown() {
        aopContextMockedStatic.close();
    }
}

如果proxy对象调用的方法是通过@Autowired注解注入的对象,可能会出现NPE。此时需要将proxy对象的注解由@Spy 改成 @Mock,并通过mockito模拟该方法的行为。而这个方法本身需要另外写一个测试方法。

与SpringBoot中单元测试如何对包含AopContext.currentProxy()的方法进行测试相似的内容:

SpringBoot中单元测试如何对包含AopContext.currentProxy()的方法进行测试

今天在工作中遇到一个问题,一个Service类中有一个方法,其中使用了 AopContext.currentProxy() 去访问自身的函数,例如 int result = ((OrderServiceImpl) AopContext.currentProxy()).save(); 单元测试方法如下

Java SpringBoot Test 单元测试中包括多线程时,没跑完就结束了

如何阻止 Java SpringBoot Test 单元测试中包括多线程时,没跑完就结束了 使用 CountDownLatch CountDownLatch、CyclicBarrier 使用区别 多线程 ThreadPoolTaskExecutor 应用 Java BasePooledObjectF

[EasyExcel] 导出合并单元格

前言 使用spring boot 对excel 进行操作在平时项目中要经常使用。常见通过jxl和poi 的方式进行操作。但他们都存在一个严重的问题就是非常的耗内存。这里介绍一种 Easy Excel 工具来对excel进行操作。 一、Easy Excel是什么? EasyExcel是阿里巴巴开源的一

简单进行Springboot Beans归属模块单元的统计分析方法

简单进行Springboot Beans归属模块单元的统计分析方法 背景 基于Springboot的产品变的复杂之后 启动速度会越来越慢. 公司同事得出一个结论. beans 数量过多会导致启动速度逐渐变慢. 之前同事写过功能进行分析. 但是本着能不影响产品就不影响产品. 我想通过其他方式进行处理.

Springboot中自定义监听器

一、监听器模式图 二、监听器三要素 广播器:用来发布事件 事件:需要被传播的消息 监听器:一个对象对一个事件的发生做出反应,这个对象就是事件监听器 三、监听器的实现方式 1、实现自定义事件 自定义事件需要继承ApplicationEvent类,并添加一个构造函数,用于接收事件源对象。 该事件中添加了

SpringBoot中几种好用的代码生成器(基于Mybatis-plus生成entity、mapper、xml等)

前言 熟悉Spring框架的同学一定都知道MVC开发模式吧,控制器(Controller)、业务类(Service)、持久层(Repository)、数据库映射(Mapper)、各种DO类构成了我们服务端的代码。初学的时候,觉得新鲜手写这些东西不觉得有啥,但是写久了就会觉得很烦。好不容易在数据库中写

[转帖]springboot中使用skywalking实现日志追踪

文章目录 SkyWalking分布式追踪系统介绍主要架构 环境引入依赖配置Log4j2下载编译好的8.7.0版本包使用探针实现日志追踪启动脚本启动Java服务访问服务 使用UI切换存储方式 SkyWalking分布式追踪系统 介绍 Skywalking是一个国产的开源框架,2015年有吴晟个人开源,

Java SpringBoot 中,动态执行 bean 对象中的方法

根据不同的条件,调用不同的 bean 对象,执行对象中的方法

SpringBoot 集成 Quartz + MySQL

Quartz 简单使用 Java SpringBoot 中,动态执行 bean 对象中的方法 源代码地址 => https://gitee.com/VipSoft/VipBoot/tree/develop/vipsoft-quartz 工作原理解读 只要配置好 DataSource Quartz 会

[转帖]SpringBoot之RedisTemplate操作redis出现\xAC\xED\x00\x05t\x00\x08乱码问题

http://qclog.cn/1118 在SpringBoot中使用RedisTemplate操作redis时,会出现\xAC\xED\x00\x05t\x00\x08这种乱码问题,特别是在使用中文时。原因是因为RedisTemplate中key和value的序列化方式都默认使用了jdk的序列化方