如何使用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
相关产品推荐
相关产品推荐

