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及注解详解

posted @ 2020-09-22 11:27  小烽  阅读(1756)  评论(0编辑  收藏  举报