用Mockito用@Transactional方法模拟一个类

时间:2019-02-08 12:47:25

标签: spring-boot junit mockito cglib

我有一个服务,一个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

我想提到的是,相同的代码在spring-boot 1.2.1和Mockito 1.10.19中也可以使用。我尝试在Spring Boot 2.1.1和Mockito 2.23.0中运行以上代码

到目前为止,我的观察结果:

  • 无论我使用的是2.1.0到2.23.0的Mockito版本,例外都是相同的。我不能(也不想)使用旧版本的Mockito,因为该项目无法再编译
  • 如果我临时删除@Transactional批注,则不会引发异常。

任何想法都必须随着Spring Boot的升级进行调整,以使测试再次起作用?

谢谢!

1 个答案:

答案 0 :(得分:1)

自版本2.1.0起,Mockito保留有关代理方法的注释。这意味着Spring尝试代理声明了事务性注释的模拟类,但失败了,因为模拟方法是最终的。

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

为避免这种情况,您将需要剥离模拟的注释。您可以使用MockSettings.withoutAnnotations