You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Mockito验证AOP日志类的错误日志抛出情况

如何使用Mockito验证AOP日志类的错误日志抛出情况

首先,我看到你已经有了一个基础的AOP日志类,先提个小细节:你的代码里有几处拼写和规范问题,比如pubic应该是public,jp.getsignature()要改成jp.getSignature()(大小写问题),类名建议首字母大写符合Java规范,先修正后的基础AOP类如下:

// 必要的导入
import org.aspectj.lang.JoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before; // 假设使用Before通知,可根据需求更换

@Component
@Aspect
public class AopClass {
    private static final Logger log = LoggerFactory.getLogger(AopClass.class);

    // 添加切点表达式,匹配你需要拦截的方法范围
    @Before("execution(* com.yourpackage..*(..))")
    public void log(JoinPoint jp) {
        log.info("hi {} and {}", jp.getSignature(), jp.getSourceLocation());
    }
}

接下来是测试部分,你提到用了MockitoExtension,但要验证AOP的日志行为,尤其是错误日志抛出的情况,我们需要结合Mockito模拟依赖,同时调整AOP类添加异常通知逻辑,下面一步步来:

第一步:给AOP类添加异常日志逻辑

如果要验证错误日志抛出,我们需要添加@AfterThrowing异常通知,用来捕获方法抛出的异常并记录错误日志:

@Component
@Aspect
public class AopClass {
    private static final Logger log = LoggerFactory.getLogger(AopClass.class);

    @Before("execution(* com.yourpackage..*(..))")
    public void log(JoinPoint jp) {
        log.info("hi {} and {}", jp.getSignature(), jp.getSourceLocation());
    }

    // 异常通知:捕获方法抛出的异常并记录error日志
    @AfterThrowing(pointcut = "execution(* com.yourpackage..*(..))", throwing = "ex")
    public void logError(JoinPoint jp, Exception ex) {
        log.error("Method {} threw exception: {}", jp.getSignature(), ex.getMessage(), ex);
    }
}

第二步:编写Mockito测试类验证日志行为

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class AopClassTest {

    // 注入要测试的AOP类
    @InjectMocks
    private AopClass aopClass;

    // Mock连接点对象,不需要真实的方法执行场景
    @Mock
    private JoinPoint joinPoint;

    // Mock签名对象,模拟方法签名信息
    @Mock
    private Signature signature;

    @Test
    public void testLogErrorRecordsExceptionCorrectly() {
        // 1. 模拟依赖对象的行为
        Exception testException = new RuntimeException("Test runtime exception");
        when(joinPoint.getSignature()).thenReturn(signature);
        when(signature.toString()).thenReturn("testTargetMethod()");

        // 2. Spy真实的Logger对象,用来捕获日志调用
        Logger originalLog = LoggerFactory.getLogger(AopClass.class);
        Logger mockedLog = spy(originalLog);

        // 3. 用反射替换AOP类中的log字段为mock对象
        try {
            java.lang.reflect.Field logField = AopClass.class.getDeclaredField("log");
            logField.setAccessible(true);
            logField.set(aopClass, mockedLog);
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 4. 调用AOP的异常日志方法
        aopClass.logError(joinPoint, testException);

        // 5. 验证错误日志是否被正确调用
        verify(mockedLog, times(1))
            .error("Method {} threw exception: {}", signature, testException.getMessage(), testException);
    }
}

几个关键提醒

  • 如果需要验证真实的AOP切面是否生效(比如切点表达式是否正确匹配目标方法),建议结合@SpringBootTest或@ContextConfiguration加载Spring上下文,而不是单纯用Mockito;如果只是测试日志逻辑,用上述mock方式足够。
  • 测试时要注意Java语法规范,避免拼写错误导致的运行时问题。
  • 验证日志时,必须spy或mock Logger对象,否则无法捕获到日志的调用记录。

备注:内容来源于stack exchange,提问作者Akash Jain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.13 16:44:42