假設我們的Project中都有一個Call API的Helper,類似這樣:
[lib/Helpers/HttpHelper.dart]
class HttpHelper {
static String? cableURL;
static String? host;
static String remoteHost = 'https://api.matchbox.com.tw';
static Client http = Client(); // <----- 重點在這
static Future<Response> doDelete(
String uri, HttpHeaderVersion v, Map? data) async {
return await http.delete(Uri.parse('${host!}$uri'),
body: json.encode(data), headers: v.header());
}
static Future<Response> doGet(String uri, HttpHeaderVersion v) async {
return await http.get(Uri.parse('${host!}$uri'),
headers: v.header());
}
static Future<Response> doPost(
String uri, HttpHeaderVersion v, Map? data) async {
return await http.post(Uri.parse('${host!}$uri'),
body: json.encode(data), headers: v.header());
}
static Future<Response> doPut(
String uri, HttpHeaderVersion v, Map? data) async {
return await http.put(Uri.parse('${host!}$uri'),
body: json.encode(data), headers: v.header());
}
}
[lib/Repositories/AuthRepo.dart]
class AuthRepo {
Future<User?> fetchCurrentUserData() async {
final response = await HttpHelper.doGet('/auth', // <----- 要Mock的URL
HttpHeaderVersion.v1, null);
try {
if (response.statusCode == 200) {
return User.fromJson(jsonDecode(response.body) as Map<String, dynamic>);
} else {
var err = ApiError.fromJson(
jsonDecode(response.body) as Map<String, dynamic>);
return Future.error(err.message ?? '');
}
} catch (e) {
return Future.error(e.toString());
}
}
}
測試可以這樣寫:
[test/helpers/MockHelper.dart]
class MockHttpClient extends Mock implements HttpClient {}
[test/widgets/MyProfilePage_test.dart]
testWidgets('When Success', (WidgetTester tester) async {
await _loadWidget(tester);
HttpHelper.http = MockClient((req) async {
if (req.url.path == '/auth') { // <----- 等於AuthRepo中要Mock的URL
return Response('{"id": 1}', 200);
}
return Response('null', 200);
});
await tester.tap(find.text('取得個人資料'));
await tester.pump();
expect(User.current?.id, 1);
expect(User.current?.isGuest, isFalse);
});
testWidgets('When Failed', (WidgetTester tester) async {
await _loadWidget(tester);
HttpHelper.http = MockClient((req) async {
if (req.url.path == '/auth') { // <----- path等於AuthRepo中doGet的URL
return Response('{"message": "Invalid Token!"}', 403);
}
return Response('null', 200);
});
await tester.tap(find.text('取得個人資料'));
await tester.pump();
expect(find.text('Invalid Token!'), findsOneWidget);
});
重點摘要
- 把原本的HttpClient換成MockClient
- 找出要Mock的URL
- 在測試中回傳期待的Response