Spring boot 用Mockito用@Transactional方法模拟类

Spring boot 用Mockito用@Transactional方法模拟类,spring-boot,junit,mockito,cglib,Spring Boot,Junit,Mockito,Cglib,我有一个服务,一个bean,它包含一个@Transactional方法: public class InMessageService { ... @Transactional public boolean retryInMessage(String messageId) { ... } } 为了进行测试,我尝试使用Mockito模拟该服务: @Bean @Primary public InMessageService inMessageService

我有一个服务,一个bean,它包含一个
@Transactional
方法:

public class InMessageService {

...

    @Transactional

    public boolean retryInMessage(String messageId) {

    ...

    }

}
为了进行测试,我尝试使用Mockito模拟该服务:

@Bean
@Primary
public InMessageService inMessageService() {
    return Mockito.mock(InMessageService.class);
}
当我开始测试时,结果是以下异常:

   Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB
subclass of class somePackage.InMessageService$MockitoMock$156222813: Common
causes of this problem include using a final class or a non-visible class;nested exception is
org.springframework.cglib.core.CodeGenerationException: java.lang.NoClassDefFoundError-->
somePath/InMessageService$MockitoMock$156222813
我想提到的是,SpringBoot1.2.1和Mockito1.10.19也使用了相同的代码。我尝试使用SpringBoot2.1.1和Mockito2.23.0运行上述代码

我迄今的观察结果:

  • 无论我使用2.1.0和2.23.0之间的Mockito版本,例外情况都是一样的。我不能(也不想)使用旧版本的Mockito,因为该项目不再编译
  • 如果临时删除
    @Transactional
    注释,则不会引发异常
你知道升级spring boot后需要调整哪些内容才能使测试再次正常工作吗


谢谢大家!

自版本2.1.0以来,Mockito在代理方法上保留注释。这意味着Spring试图代理声明事务注释的mock类,但失败了,因为mocking方法是final

之前,Mockito剥离了这些注释,这些注释会导致任何真正的方法调用由于缺少事务而失败


为了避免这种情况,您需要去掉mock的注释。您可以使用
MockSettings.withoutAnnotations

执行此操作,我理解。注释不是由重写方法“继承”的吗?我尝试了你的变通建议,我也得到了同样的子类例外。我发现如果你不想使用内联mock maker,我们已经添加了一个功能来去除注释。查看我的更新答案。我刚刚尝试了Mockito.mock(InMessageService.class,Mockito.withSettings()。withoutAnnotations());但它仍然不起作用。还有比这更多的事要做吗?