教你為 Riverpod 2.0 撰寫 Flutter 測試,使用 Mocktail 讓你輕鬆不畏懼! part.1
說明 Mocktail 幾個常用的 API
Mocktail
本文都會使用到 Mocktail 套件,優點是方便設置假資料,只需要一行即可使用 Mock class 開始測試,不需要額外生成測試代碼。透過 Mocktail 我們需要建立一個 Mock class 並繼承 Mock
,代表可以進行假資料的驗證。接著實作定義好的介面,讓我們針對每個函式進行資料偽造。
提醒:建議開發都以 DI 去進行實作,其中的依賴反轉原則為每個服務以及資料類定義抽象介面,提供靈活性以及測試性。
// Mock class
class MockLocalStorage extends Mock implements LocalStorage {}
abstract class LocalStorage {
Future<void> init();
bool has(String key);
Future<String?> get(String key);
Future<void> set(String key, dynamic data);
}
API for arrangement
when()
- 當做了什麼事
- 裡面通常放函式
thenReturn()
函式為同步,返回同步資料
when(() => storage.has('isGood')).thenReturn((_) => true);
thenAnswer()
函式為非同步,返回非同步資料
// 1.
when(() => storage.get('isGood')).thenAnswer((_) async => 'true');
// 2.
when(() => storage.get('isGood')).thenAnswer((_) => Future.value('true'));
thenThrow()
拋出 Exception,模擬出錯的情況
when(() => storage.has('isGood')).thenThrow(Exception('Can not get data!'));
API for verification
expect()
期望操作能得到什麼結果,檢查是否跟自己前面安排的偽造資料相同,驗證資料在邏輯處理後是否能給予預期結果。
expect(getAppThemeMode(), const AsyncData<ThemeMode>(ThemeMode.dark));
Ex: 透過 getAppThemeMode()
取得 ThemeMode,因為它為 FutureProvider 有非同步處理,我預期會得到指定的 AsyncData<ThemeMode>
expectLater()
跟 except 一樣,只是裡面先進行非同步操作
await expectLater(() async => getAppThemeModeAsync(), throwsA(isA<Exception>()));
Ex: 透過 getAppThemeModeAsync()
取得 ThemeMode,前面安排在取資料的過程會拋出例外,所去預期會有 Exception
verify()
- 驗證某個函式是否被呼叫或使用過,也可以指定使用過的次數,檢查跟實際我們想要的情境是否相同。
- 驗證過的操作或流程會被後面忽略,不能重複相同驗證否則會報錯
// Do some operation
final bool isGood = checkIsGood();
.
.
.
/// Choose one of two ways
// 1.
verify(() => storage.get('isGood'))
// 2.
verify(() => storage.get('isGood')).called(1);
Ex: 使用到 checkIsGood()
檢查狀態,裡面可能有一些邏輯,其中包含跟 storage 拿資料,我在後面驗證它實際上函式有沒有被呼叫,也檢查是否只呼叫過一次
verifyInOrder()
驗證多個情況,照順序檢查是否正確,每個情境只有一個,不行重複確認
verifyInOrder([
// Get current ThemeMode
() => listener(null, const AsyncLoading<ThemeMode>()),
() => listener(const AsyncLoading<ThemeMode>(), const AsyncData<ThemeMode>(ThemeMode.light)),
// Change to ThemeMode.dark
() => listener(const AsyncData(ThemeMode.light), const AsyncData(ThemeMode.dark)),
]);
Ex: 檢查更新 ThemeMode 的情境,從 ThemeMode.light 切換到 ThemeMode.dark
verifyNoMoreInteractions()
驗證某個物件、函式是否沒有新的存取和互動了
verifyNoMoreInteractions(storage);
verifyNever()
驗證物件、函式是否從來沒有使用過
verifyNever(storage.get('isGood'))
Matcher
any()
代表任何東西,可能是物件、函式,當無法百分百給予實際值的時候很適合使用
any(that: )
檢查結果是否為指定型別,可以搭配 isA<XXX>()
any(
that: isA<AsyncError<ThemeMode>>(),
),
到這邊休息一下,我想你已經大概了解一些寫測試的技巧了,如果準備好的話,可以先嘗試使用 Mocktail 撰寫簡易的測試,慢慢熟悉它
下一篇
其他文章
- Flutter 輕鬆實作 i18n,使用 easy_localization_generator 就對了
- Flutter CICD 使用 Gitlab Runner 和 App Center 實作 part.1
- 使用 CodeMagic 和 Firebase 實現 Flutter CICD
- 輕鬆完成Flutter開發環境,最新版!
- 實作Flutter多變有趣的滾動效果CustomScrollView!
- 如何在Flutter使用 Makefile 節省你的時間?
- Easily understand StatefulWidget LifeCycle of Flutter
- “freezed” makes model class strong and easily
- 提高Flutter性能的小技巧!(一)
- 提高Flutter性能的小技巧!(二)
- 提高Flutter性能的小技巧!(三)
- What are Async and Isolates in Flutter?
- LoadBalancer is optimization for Isolates in Flutter
- Riverpod 輕鬆學,原來這麼好用!
- Riverpod 輕鬆學(二),一些進階用法!
關於我
- GitHub:
- Instagram:
- Linkedin:
- Youtube:
- Youtube: (美食頻道)
- Email: [email protected]
贊助
謝謝你花費時間看完,非常感謝!
如果覺得文章不錯的話可以贊助,讓我有更多動力和熱情分享學習紀錄和生活!
最後
希望有幫助到你/妳,歡迎追蹤我,方便瀏覽最新的文章~