springboot 中 Mock 三方接口測試service類


1、背景

在 業務邏輯中間需要調用 三方部門的接口,但三方接口還在開發中,只提供了 接口名稱,自己業務已經開發完成,所以需要Mock 掉單三方的 調用。

2、 使用Mock進行測試

需求是 要 部分mock的形式(只mock 三方的接口),其他 bean 使用真實的實例。

使用 @SpringbootTest, 啟動容器測試。

調用方法1相關的部分鏈路

XxxInfoService->XxxInfoService: 測試目標方法類
XxxInfoService->XxxApiService: 三方接口
XxxInfoService->XxxInvokeService: 操作db
XxxInfoService->....: 其他操作
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class MockTest {
    /**
     * 其他 未 定義 @Mock 的類,通過 spring注入到 IOC中
     */
    @Autowired
    @InjectMocks
    private XxxInfoService xxxInfoService;

    //需要 mock 執行的 類
    @Mock
    private XxxApiService xxxApiService;


    @Before
    public void init() {
      //Mock IOC
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void test() throws IOException {

        //同@Mock 二選一
//        xxxApiService = Mockito.mock(XxxApiService.class);
        XxxResponseBase responseBase =  new XxxResponseBase();
        responseBase.setCode(0);
      	//Mock 三方接口的 result
        Mockito.when(xxxApiService.feedbackOrderSubmit(any()))
                .thenReturn(responseBase);

        Config config = new Config();
        config.setOrderId("123");
        xxxInfoService.notifyOss(config);
    }
}

結果:執行成功,並且 db中插入 記錄

調用方法2的 部分調用鏈路,所有數據的獲取都需要mock

XxxInfoService->XxxInfoService: 測試目標方法類
XxxInfoService->XxxApiService: 三方接口 mock
XxxInfoService->XxxService: 查詢 mock
XxxInfoService->aaaService: 三方接口 mock
XxxInfoService->XxxInvokeService: 操作db
XxxInfoService->....: 其他操作
public void test_syncData() {

        String orderId="1";
        List<InfoDO> successServers= Arrays.asList(new InfoDO());
        InfoConfig infoConfig= new InfoConfig();
        infoConfig.setBasicConfig(new BasicConfig());
        infoConfig.getBasicConfig().setOrderId(orderId);
        infoConfig.getBasicConfig().setWid("1");
        infoConfig.getBasicConfig().setCid(1);
        infoConfig.getBasicConfig().setServiceId(2);
        infoConfig.getBasicConfig().setIpServiceId(3);
        infoConfig.getBasicConfig().setBwServiceId(4);

        XxxOrderDO order = new XxxOrderDO();
        order.setDesc("test");
        Mockito.when(orderService.getOrder(any())).thenReturn(order);

        ServerInfo serverInfo = new ServerInfo();

        serverInfo.setDetail(new XxxDetailResponse.Detail());
        serverInfo.getDetail().setInfo(new XxxDetailResponse.Info());
        serverInfo.getDetail().getInfo().setOsName("os");
        serverInfo.getDetail().getInfo().setLcUuid("uuid");
        serverInfo.getDetail().getInfo().setLabel("lable");
        serverInfo.getDetail().getInfo().setSn("sn");
        serverInfo.getDetail().getInfo().setOrderId(123);
        serverInfo.getDetail().getInfo().setZoneName("Lax");
        serverInfo.getDetail().getInfo().setName("pre");
        serverInfo.getDetail().getInfo().setStartTime("2020-12-12 10:12:12");
        serverInfo.getDetail().getInfo().setOwnWanIp("10.10.10.10");

        serverInfo.getDetail().getInfo().setWanLanId(0);

        serverInfo.getDetail().getInfo().setWanSwIfname("ddff");
        serverInfo.getDetail().getInfo().setSnmpIp("10.22.22.22");
        Mockito.when(aaaService.serverDetail(any(),any())).thenReturn(serverInfo);

        xxxResponseBase responseBase =  new xxxResponseBase();
        responseBase.setCode(0);
        Mockito.when(xxxApiService.synaaaData(any())).thenReturn(responseBase);

       //場景1 
        xxxInfoService.syncData(successServers, infoConfig, true,orderId);


        // 場景 2
        serverInfo.getDetail().getInfo().setWanLanId(1);
        GetVpcVlanResponse response = new GetVpcVlanResponse();
        response.setData(new GetVpcVlanResponse.Data());
        response.getData().setPortName("port--");
        response.getData().setSnmpIP("122--");
        GetVpcVlanResponse.Server server = new GetVpcVlanResponse.Server();
        server.setLcuuid("111");
        response.getData().setServers(Arrays.asList(server));
        response.setSuccess(true);
        Mockito.when(aaaService.getVpc(any(),any())).thenReturn(response);

        ServerDetailListResponse serverDetailListResponse = new ServerDetailListResponse();
        XxxDetailResponse.Detail detail = new XxxDetailResponse.Detail();
        XxxDetailResponse.Info info = new XxxDetailResponse.Info();
        info.setSnmpIp("33");
        info.setWanSwIfname("info-33");
        detail.setInfo(info);
        serverDetailListResponse.setDetail(Arrays.asList(detail));
        serverDetailListResponse.setSuccess(true);
        Mockito.when(aaaService.serverDetails(any(),any())).thenReturn(serverDetailListResponse);

        xxxInfoService.syncData(successServers, infoConfig, true,orderId);
        
        //場景3 faied
        xxxInfoService.syncData(new ArrayList<>(), infoConfig, true,orderId);
    }

3、在查詢資料過程中,看到

大概瀏覽了下下 Mock文檔, 看了一些基本的操作, 還在 Testing in Spring Boot 中發現,並不需要啟動整個環境進行測試,在上面的測試中,自己也有感覺,這是用到了幾個類,啟動整個環境太重了。 可以通過不同的注解 分層測試。有興趣大家可以自己看看。

  • Integration Testing With@DataJpaTest

  • Mocking With @MockBean

    • 結合 @TestConfiguration 加載 Bean
  • Unit Testing With @WebMvcTest

總結

1、Mockito 框架功能很多,我只差了 我要用到的部分,
2、為了能更好的分層測試,在代碼編寫過程中注意 分層。
3、操作數據多的情況下,工作量還是很大的。
4、對靜態類的Mock 需要使用PowerMock。
5、typora 中畫圖功能強大。

mock 使用2中有了 更清晰的了解.


免責聲明!

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



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