Flutter Test CI通用方案詳解

在Flutter Test官方的CI方案中,包含UnitTest/WidgetTest/DriverTest三種模式,其中UnitTest/WidgetTest是可以在代碼的沙盒環(huán)境下運行,而Driver Test需要依賴整包構(gòu)建;大家都知道在單元測試過程中發(fā)現(xiàn)問題成本最低,而整包構(gòu)建耗時比較久,因此這里介紹一種通用的Flutter Test在CI階段的方案;

Flutter CI自動化檢測能力主要通過FlutterTest能力建設,但具體數(shù)據(jù)能力建設稍有不足,主要原因是

    1. FlutterTest不支持直接發(fā)送一個http請求功能;
    1. 以及大量的Channel數(shù)據(jù)需要主動MOCK,如果大型應用需要mock的太多太雜;

同理可以看在stackoverflow上也有很多人咨詢過為什么flutter test環(huán)境下無法運行一個HTTP服務請求; https://stackoverflow.com/questions/62184160/flutter-testing-passing-an-actual-http-client-instead-of-a-mocked-one

其實分析主要原因是一個在Flutter Test的沙盒環(huán)境下,無法運行engine側(cè)很多代碼,導致socket服務不能正常發(fā),因此在CI下網(wǎng)絡服務是斷開的;鑒于此很多mock服務比如flutter mockite就提供一種方案自己維護mock數(shù)據(jù),但是這種方式維護成本就非常高了,大家都是程序員,誰也不愿意去維護mock數(shù)據(jù),何況業(yè)務天天變動情況下; 分析下其思路主要是通過setupMockHttpOverrides覆蓋全局的Http,然后將請求服務轉(zhuǎn)接到mock處理邏輯中;

void setupMockHttpOverrides() {
  HttpOverrides.global = MockHttpOverrides();
}

/// mock 模擬 http
class MockClient extends Mock implements http.Client {}
void main() {
    test("testHttp", () async {
      final client = MockClient();
      when(client.get("xxxx"))
          .thenAnswer((_) async {
        return http.Response(
            '{"title": "test title", "body": "test body"}', 200);
      });
      var post = await fetchPost(client);
      expect(post.title, "test title");
    });

2. 方案

介紹了上述的那種方案,肯定狗都直搖頭,本文主要介紹一種投機方案解決CI服務,我們發(fā)現(xiàn),flutterTest是可以運行一些Dart代碼,但是httpClient運行到sky_engine的一些代碼邏輯時候就沒有返回值,導致無法發(fā)送一個http請求出去,但是無意偶然機會發(fā)現(xiàn)官方介紹Process,其通過Process.run可以實現(xiàn)一些shell命令:

既然可以運行Shell命令,即可以通過CURL發(fā)送一個http請求,在flutterTest環(huán)境中發(fā)送如下:

 test('httpTest', () async {
    ProcessResult result = await Process.run('curl', [
      'http://www.baidu.com',
    ]);
    String serverResponse = result.stdout();
  });

遺憾是實際測試發(fā)現(xiàn)在flutterTest環(huán)境中運行在Process.run也卡住沒有返回值,跟進代碼發(fā)現(xiàn)有一個同步方式Process.runSyn發(fā)現(xiàn)可以正常返回值:

image.png

于是乎我們就可以使用Process.runSyn方法通過CURL命令繞過HTTP服務缺陷,發(fā)送一個真實的網(wǎng)絡服務了;

解決完網(wǎng)絡服務,其次就是Channel服務能力,這塊官方的推薦方案是:

 MethodChannel('flutter_mock_service').setMockMethodCallHandler((MethodCall methodCall) async {
  if (methodCall.method == 'getPlatformVersionMock') {
    return 'Android 11 Mock';
  }
  return null;
});

但是很多大型應用HTTP服務都是從MethodChanenl走到Native發(fā)送出去的,因此如果HTTP服務都需要自己MOCK,那單測寫死的心都有了,在我上一篇文章介紹Flutter 構(gòu)建PlayGround極速方案有介紹如何HOOK MethodChanenl,并且在宿主APP開啟一個網(wǎng)絡服務能力,我們完全可以使用CURL將Channel的服務打到宿主APP上,然后通過此方式就可以快速MOCK出任何Channel服務能力;

個人已經(jīng)實現(xiàn)一個flutter 2.5.x版本的插件方案,歡迎白嫖flutter_mock_service

3. 擴展

本文主要介紹了在FlutterTest環(huán)境下如何通過CURL方案可以HOOK住 HTTP服務以及MethodChannel服務,但是flutter_mock_service更多細節(jié)我還沒介紹,等后續(xù)在開坑介紹~

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容