Spring AOP AfterThrowing 方面不适用于 Junit 5 中的模拟对象

Spring AOP AfterThrowing aspect doesn't work with mock objects in Junit 5

在我的 spring 项目中,我创建了一个简单的方面,它捕获 DaoExceptions 并将它们转化为服务异常

@Aspect
@Component
public class ExceptionAspect {

    @Pointcut("execution(public * *(..))")
    private void allPublicMethods() {

    }
    
    @Pointcut("within(img.imaginary.dao.*)")
    private void inDao() {

    }
    
    @AfterThrowing(pointcut = "allPublicMethods() && inDao()", throwing = "exception")
    public void afterThrowing(JoinPoint joinPoint, DaoException exception) {
        throw new ServiceException(String.format("%s in method %s %s class", exception.getMessage(),
                joinPoint.getSignature().getName(), joinPoint.getTarget().getClass().getSimpleName()), exception);
    }  
}

并且当从 dao 层抛出 DaoException 到 service 它变成 Service exception 时它工作正常

但只是没有在测试中:

@Test
void findById_ShouldThrowServiceException_WhenEntityNotFound() {
    Mockito.when(defaultDao.findById(0)).thenThrow(DaoException.class);        
    assertThrows(ServiceException.class, () -> defaultServiceImpl.findById(0));
}

在这个测试中,我有一个 defaultDao,它是一个 Mock 对象,当它抛出 DaoException 时,我的方面没有捕获并代理它

我不知道如何解决这个问题

根据以下假设 - 它是一个 spring-boot 项目,defaultDao 是一个使用 @MockBean

的模拟 bean

请仔细阅读 issue 以了解为什么 @MockBean 不起作用。

以下代码将模拟一个 bean 并抛出异常。您将需要调整代码以使其适合您。(例如:您的情况可能需要也可能不需要 @SpringBootTest)。

@SpringBootTest
class DefaultDaoTest {

    @Autowired
    DefaultDao defaultDao;

    @Test
    void test() {
        assertThrows(ServiceException.class, () -> defaultDao.findById(0));
    }

}

@Configuration
class TestConfig {
    @Bean
    @Primary
    public DefaultDao defaultDao() {
        return new DefaultDao() {
            @Override
            public Object findById(Long id) {
                throw new DaoException();
            }
        };
    }
}