我正試圖為一個螢屏撰寫一個小部件測驗,而不是主應用程式。這是我第一次寫小部件測驗,我找不到合適的解決方案。 我不知道如何為這個寫一個合適的測驗。我試著寫了一個簡單的widget測驗,結果卻給我一個錯誤,如下所示 "警告。本套件中至少有一個測驗創建了一個HttpClient。當 運行一個使用TestWidgetsFlutterBinding的測驗套件時,所有HTTP 請求將回傳狀態代碼400,并且沒有網路請求會 實際進行。任何期望有真實網路連接和 狀態代碼的測驗都會失敗。 要測驗需要HttpClient的代碼,請提供你自己的HttpClient 的實作,以便你的測驗能夠 始終為被測代碼提供一個可測驗的回應"。 我剛剛開始學習,請幫助我。 注意:我的測驗只是寫了一個尋找文本小部件的基本測驗。
class BookingDetails extends StatefulWidget {
final booking。
BookingDetails(this.booking)。
@override
_BookingDetailsState createState() => _BookingDetailsState()。
}
class _BookingDetailsState extends State< BookingDetails>
with AutomaticKeepAliveClientMixin {
Row _buildTeacherInfo(Map<String, dynamic> teacherData) {
return teacherData != null ?
? 行(
children: <Widget>[
CircleAvatar(
半徑。53,
backgroundColor: MyColors.primary,
孩子。CircleAvatar(
半徑。50.0,
backgroundImage: teacherData['user']['img_url'] == null ||
teacherData['user']['img_url'] == ' '
? AssetImage('assets/images/placeholder_avatar.png')
: NetworkImage(teacherData['user']['img_url'] )。
backgroundColor: Colors.transparent,
),
),
SizedBox(width: 20.0)。
列(
children: <Widget>[
容器(
child: Column(
children: <Widget>[
文本(
'${teacherData['user']['first_name']} '。
風格。AppStyles.textHeader1Style,
),
文本(
'${teacherData['user']['last_name']}'/span>,
風格。AppStyles.textHeader1Style,
),
],
),
),
提升的按鈕(
onPressed: () {
//查看簡介方法。
},
樣式。ElevatedButton.styleFrom(
primary: MyColors.primary,
形狀。const RoundedRectangleBorder(
borderRadius: borderRadius.all(Radius.round(25))。
),
孩子。行(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Icon(Icons.next_plan_outlined)。
SizedBox(width: 10.0) 。
Text('VIEW PROFILE'),
],
),
),
],
),
],
)
: 行(
children: <Widget>[
CircleAvatar(
半徑。48,
backgroundColor: MyColors.primary,
孩子。CircleAvatar(
半徑。45.0,
背景圖片。
AssetImage('assets/images/placeholder_avatar.png')。
backgroundColor: Colors.transparent,
),
),
SizedBox(width: 20.0)。
擴展的(
孩子。文本(
'教師分配在進行中'。
風格。AppStyles.textHeader1Style,
),
)
],
);
}
小工具 _buildBookingDetails(
Map<String, dynamic> booking,
List<dynamic> campusData, //一個校區的資料由于某種原因是一個陣列。。
Map<String, dynamic> instData,
) {
return Expanded(
孩子。Scrollbar(
child: ListView(
children: [
ListTile(
領導。Icon(Icons.location_on)。
標題。文本(
'${campusData[0]['address_line1']}, '
' ${campusData[0]['suburb']}, '
'${campusData[0]['state']} ${campusData[0]['postcode']}',
風格。AppStyles.textHeader3Style,
),
),
}
@override
Widget build(BuildContext context) {
super.build(context)。
return FutureBuilder(
未來。Future.wait([_teacherData, _campusData, _classData, _instData])。
構建者。(context, snapshot) => snapshot.connectionState ==
ConnectionState.waiting
? MyLoadingScreen(message: '加載預訂資料,請等待...')
: snapshot.hasData
? SafeArea(
孩子。容器(
margin: const EdgeInsets.only(top: 30.0) 。
孩子。Padding(
padding: const EdgeInsets.all(30) 。
孩子。列(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
_buildTeacherInfo(snapshot.data[0] )。
Divider(color: MyColors.dividerColor)。
SizedBox(高度:10)。
const SizedBox(height: 10)。
分割器(
color: MyColors.primary,
厚度。1,
),
const SizedBox(高度:10)。
_buildBookingDetails(
widget.booking。
snapshot.data[1]。
snapshot.data[3]。
),
SizedBox(高度:10)。
分割器(
color: MyColors.primary,
厚度。1,
),
SizedBox(高度:10)。
中心(
child: widget.booking['cancelled_by_inst'] == true ?
? 文本(
'cancelled',
風格。AppStyles.textHeader3StyleBold,
: widget.booking['teacher_id'] == null ?
? 中心(
孩子。文本(
'Teacher Allocation in Progress',
風格。AppStyles.textHeader3StyleBold,
),
)
: null。
),
uj5u.com熱心網友回復:
我把你的代碼縮減為以下最小的版本,以便能夠執行它:
snipppping
我把你的代碼縮減為以下最小的版本。
snippet.dart:
import 'package:flutter/material.dart'/span>。
import 'dart:convert';
import 'api.dart';
class BookingDetails extends StatefulWidget{
final Map<String, String> booking。
BookingDetails(this.booking)。
@override
_BookingDetailsState createState() => _BookingDetailsState()。
}
class _BookingDetailsState extends State< BookingDetails> {
late Future _campusData;
Future<dynamic> _fetchCampusData() async{
var campusID = widget.booking['campus_id']。
if (campusID != null) {
var response = await api.getCampusByID(campusID);
return json.decode(response.body)。
}
}
@override
void initState() {
_campusData = _fetchCampusData()。
super.initState()。
}
@override
Widget build(BuildContext context) {
return FutureBuilder(
未來。_campusData,
builder: (context, snapshot) {
if ( snapshot.hasData) {
return const Text('顯示資料')。
} else if (snapshot.hasError) {
return const Text('An error occurred. ');
} else {
return const Text('Loading...') 。
}
}
);
}
}
api.dart:
import 'package:http/http.dart' as http;
final _ApiClient api = _ApiClient()。
class _ApiClient {
Future<http.Response> getCampusByID(String id) async{
var url = Uri.parse('https://run.mocky.io/v3/49c23ebc-c107-4dae-b1c6-5d325b8f8b58') 。
var response = await http.get(url)。
if (response.statusCode >= 400) {
throw "An error occurred"。
}
return 回應。
}
下面是一個小工具測驗,它重現了你所描述的錯誤:
import 'package:flutter/material.dart'/span>。
import 'package:flutter_test/flutter_test.dart';
import 'package:widget_test/snippet.dart'。
void main() {
testWidgets('Should test widget with http call', (WidgetTester tester) async {
var booking = <String, String> {
'campus_id': '2f4fccd2-e199-4989-bad3-d8c48e66a15e'
};
await tester.pumpWidget(TestApp(BookingDetails(booking)) )。
expect(find.text('Loading...'), findsOneWidget) 。
await tester.pump()。
expect(find.text('Displaying data'), findsOneWidget) 。
});
}
class TestApp extends StatelessWidget{
final Widget child。
TestApp(this.child)。
Widget build(BuildContext context) {
return MaterialApp(
home: child,
);
}
測驗失敗。請看上面的例外日志。
測驗的描述是。應該測驗widget with http call
警告。至少有一個測驗在 這個套件創建了一個HttpClient。當
運行一個使用TestWidgetsFlutterBinding的測驗套件時,所有HTTP
請求將回傳狀態代碼400,并且沒有網路請求將被實際執行。
實際進行。任何期望有真實網路連接和
狀態代碼的測驗將失敗。
要測驗需要HttpClient的代碼,請提供你自己的HttpClient
的實作,以便你的測驗能夠
始終如一的為被測代碼提供可測驗的回應。
解決方案[/h4
這個錯誤告訴你問題出在哪里:你不能在 widget 測驗中執行 HTTP 呼叫。所以你需要模擬那個HTTP呼叫,讓模擬的呼叫代替真正的HTTP呼叫。有很多方法可以做到這一點,例如使用mockito 包。
這里有一個可能的解決方案,使用nock包,在HTTP級別模擬HTTP回應。
pubspec.yaml:
dev_dependencies:
nock: ^1.1.2
Widget測驗:
import 'dart:convert';
import 'package:flutter/material.dart'。
import 'package:flutter_test/flutter_test.dart';
import 'package:nock/nock.dart';
import 'package:widget_test/snippet.dart';
void main() {
setUpAll(nock.init)。
setUp(() {
nock.cleanAll()。
});
testWidgets('Should test widget with http call', (WidgetTester tester) async {
nock('https://run.mocky.io')
.get('/v3/49c23ebc-c107-4dae-b1c6-5d325b8f8b58'/span>)
.reply(200, json.encode('{"id": "49c23ebc-c107-4dae-b1c6-5d325b8f8b58", "name": "示例校園" }'))。
var booking = <String, String> {
'campus_id': '2f4fccd2-e199-4989-bad3-d8c48e66a15e'
};
await tester.pumpWidget(TestApp(BookingDetails(booking)) )。
expect(find.text('Loading...'), findsOneWidget) 。
await tester.pump()。
expect(find.text('Displaying data'), findsOneWidget) 。
});
}
class TestApp extends StatelessWidget{
final Widget child。
TestApp(this.child)。
@override
Widget build(BuildContext context) {
return MaterialApp(
home: child,
);
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/328685.html
標籤:
