zoukankan      html  css  js  c++  java
  • Mock的使用2

    背景

    ​ 想重新执行下 以前写的 mock 测试类,发生了一堆的问题,进行部分的梳理和深究。

    1、执行mock方法时 异常

    org.mockito.exceptions.base.MockitoException: 
    Mockito cannot mock this class: class com.zenlayer.delivery.biz.service.ConfigService.
    
    Mockito can only mock non-private & non-final classes.
    If you're not sure why you're getting this error, please report to the mailing list.
    
    
    Java               : 11
    JVM vendor name    : JetBrains s.r.o
    JVM vendor version : 11.0.4+10-b304.77
    JVM name           : OpenJDK 64-Bit Server VM
    JVM version        : 11.0.4+10-b304.77
    JVM info           : mixed mode
    OS name            : Mac OS X
    OS version         : 10.15.6
    
    
    Underlying exception : java.lang.UnsupportedOperationException: Cannot define class using reflection
    	.....
    Caused by: java.lang.IllegalStateException: Could not find sun.misc.Unsafe
    	at net.bytebuddy.dynamic.loading.ClassInjector$UsingUnsafe$Dispatcher$Disabled.initialize(ClassInjector.java:1366)
    	......
    Caused by: java.lang.NoSuchMethodException: sun.misc.Unsafe.defineClass(java.lang.String, [B, int, int, java.lang.ClassLoader, java.security.ProtectionDomain)
    	......
    	... 58 more
    

    编译时 JDK 版本变成 11了

    修改:idea-->ProjectStructures-->Modules (语法检测)

    2、mock 测试 不成功

    mock的方法在 目标方法中未生效。

    @Mock @InjectMocks @MockBean 使用有点乱。需要理理思绪!!!

    /**
     * @Mock 生效
     */
    //@RunWith(org.mockito.runners.MockitoJUnitRunner.class) //
    
    /**
     * @RunWith(SpringJUnit4ClassRunner.class) + init
     * @Mock 不生效
     */
    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringBootTest
    public class ReservedServiceMockTest {
    
    
        @Autowired
        @InjectMocks
        private ReservdServerService reservdServerService;
    
    //    @Mock
    //    @Autowired
    //    @MockBean
        @Mock
        private ConfigService configService;
    
    //    @Autowired
    //    @MockBean
        @Mock
        private OrderManager orderManager;
    
        /**
         * @Mock 在当前测试 方法直接调用中生效, 但在 目标类中调用 无效
         * @MockBean 能 实现。 Springboot 中,使用 @MockBean 加入到 容器中
         */
    
    
        @Before
        public void init() {
            MockitoAnnotations.initMocks(this);
        }
    
    
        @Test
        public void test_check_reserved() throws JsonProcessingException {
    
            DeliveryOrderDO order = new DeliveryOrderDO();
            order.setOrderId("test_check_1");
            OrderExtendParam param = new OrderExtendParam();
            param.setTargetCount(3);
            param.setReservedTotalCount(2);
            param.setThisOrderReservedCount(2);
            order.setExtendParam(JsonUtils.writeValueAsString(param));
    
            InfoConfig infoConfig = new InfoConfig();
            BasicConfig basicConfig = new BasicConfig();
            basicConfig.setZoneId(2);
            basicConfig.setModelId(2);
            basicConfig.setCid(3345);
            infoConfig.setBasicConfig(basicConfig);
    
            Mockito.when(configService.getInfoConfig(any())).thenReturn(infoConfig);
    
            InfoConfig infoConfig1 = configService.getInfoConfig("1");
            Mockito.when(orderManager.update(any())).thenReturn(true);
    
            reservdServerService.doReserveServer(order);
    
    
            System.out.println("over!!!");
        }
    }
    

    现象:

    @Mock

    在当前测试方法直接调用,mock 生效

    目标类中 mock 没生效

    查看service类:并不是同一个

    @MockBean

    调用mock都生效成功。

    实践中的一些点记录:

    1、@RunWith(SpringJUnit4ClassRunner.class) + @SpringBootTest + MockitoAnnotations.initMocks(this); 模式下,@Mock 在当前test 方法中生效,到 目标类方法中 mock 失效。

    ​ > 在spring 容器中 的 service 和mock的service 不是同一个对象导致。

    2、使用 @MockBean 注解, 都生效(放入 spring IOC中)

    ​ > 使mock的bean 放入 spring IOC中,即 mock的对象和容器中的对象时同一个

    3、@RunWith(org.mockito.runners.MockitoJUnitRunner.class) 注解下,使用@InjectMocks和 @Mock 注解 ,在 目标类方法中 mock成功。(非 spring 容器环境)

    进一步理解:

    1、@Mock 和 @InjectMocks 一起 使用。 @RunWith(org.mockito.runners.MockitoJUnitRunner.class) 初始化了 @Mock 和@InjectMocks。

    在 一个service中,需要调用 多个 其他service的时候,要么对 所有的 service进行mock,可以生效,如果(在spring 容器中) 只想对某两个 service进行mock, 其他 正常调用的话,需要把 mock的 service 放入到 Spring容器中才行,即直接使用 @MockBean即可。
    

    2、@SpringBootTest 下,使用 @MockBean(org.springframework.boot.test.mock.mockito包下) 即可

    3、在使用中,需要根据 测试类的场景,进行合理的选择使用 @Mock,@InjectMocks,@MockBean 这些注解,让 测试和执行更高效。

    参考:

    Spring Boot - Unit Testing and Mocking with Mockito and JUnit

    关于java:@ Mock,@ MockBean和Mockito.mock()之间的区别

    SpringBoot Test及注解详解

  • 相关阅读:
    asp.net mvc实现图片下载防盗链及提示是否存在!
    Asp.net mvc + Javascript 灵活的网站广告解决方案
    我自己Diy的asp.net mvc框架,支持多级目录!
    在asp.net mvc中创建使用Linq to sql的分页控件
    用asp.net开发移动wap网站集成在线wap模拟器
    .net平台下的手机在线wap网站模拟器(附源代码)
    opensuse 11.1 安装flashplayer
    引用第三方类库的私有类与私有方法
    如何统计代码行执行的时间?
    linux mono 调用windows sqlServer 2005
  • 原文地址:https://www.cnblogs.com/idea-persistence/p/13711042.html
Copyright © 2011-2022 走看看