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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM