- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试为屏幕而不是主应用程序编写小部件测试。这是我第一次编写小部件测试,我找不到合适的解决方案。我不知道如何为此编写适当的测试。我尝试编写一个简单的小部件测试,但最终出现如下错误“警告:此套件中至少有一个测试会创建一个 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
? Row(
children: <Widget>[
CircleAvatar(
radius: 53,
backgroundColor: MyColors.primary,
child: CircleAvatar(
radius: 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),
Column(
children: <Widget>[
Container(
child: Column(
children: <Widget>[
Text(
'${teacherData['user']['first_name']} ',
style: AppStyles.textHeader1Style,
),
Text(
'${teacherData['user']['last_name']}',
style: AppStyles.textHeader1Style,
),
],
),
),
ElevatedButton(
onPressed: () {
//View Profile method
},
style: ElevatedButton.styleFrom(
primary: MyColors.primary,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(25))),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Icon(Icons.next_plan_outlined),
SizedBox(width: 10.0),
Text('VIEW PROFILE'),
],
),
),
],
),
],
)
: Row(
children: <Widget>[
CircleAvatar(
radius: 48,
backgroundColor: MyColors.primary,
child: CircleAvatar(
radius: 45.0,
backgroundImage:
AssetImage('assets/images/placeholder_avatar.png'),
backgroundColor: Colors.transparent,
),
),
SizedBox(width: 20.0),
Expanded(
child: Text(
'Teacher allocation in progress',
style: AppStyles.textHeader1Style,
),
)
],
);
}
Widget _buildBookingDetails(
Map<String, dynamic> booking,
List<dynamic> campusData, // one campus' data is an array for some reason.
Map<String, dynamic> instData,
) {
return Expanded(
child: Scrollbar(
child: ListView(
children: [
ListTile(
leading: Icon(Icons.location_on),
title: Text(
'${campusData[0]['address_line1']},'
' ${campusData[0]['suburb']}, '
'${campusData[0]['state']} ${campusData[0]['postcode']} ',
style: AppStyles.textHeader3Style,
),
),
}
@override
Widget build(BuildContext context) {
super.build(context);
return FutureBuilder(
future: Future.wait([_teacherData, _campusData, _classData, _instData]),
builder: (context, snapshot) => snapshot.connectionState ==
ConnectionState.waiting
? MyLoadingScreen(message: 'Loading booking data, please wait...')
: snapshot.hasData
? SafeArea(
child: Container(
margin: const EdgeInsets.only(top: 30.0),
child: Padding(
padding: const EdgeInsets.all(30),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
_buildTeacherInfo(snapshot.data[0]),
Divider(color: MyColors.dividerColor),
SizedBox(height: 10),
const SizedBox(height: 10),
Divider(
color: MyColors.primary,
thickness: 1,
),
const SizedBox(height: 10),
_buildBookingDetails(
widget.booking,
snapshot.data[1],
snapshot.data[3],
),
SizedBox(height: 10),
Divider(
color: MyColors.primary,
thickness: 1,
),
SizedBox(height: 10),
Center(
child: widget.booking['cancelled_by_inst'] == true
? Text(
'Canceled',
style: AppStyles.textHeader3StyleBold,
)
: widget.booking['teacher_id'] == null
? Center(
child: Text(
'Teacher Allocation in Progress',
style: AppStyles.textHeader3StyleBold,
),
)
: null,
),
}
最佳答案
我已将您的代码缩减为以下最小版本,以便能够执行它:
snippet.dart
:
import 'package:flutter/material.dart';
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(
future: _campusData,
builder: (context, snapshot) {
if (snapshot.hasData) {
return const Text('Displaying data');
} 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 response;
}
}
这是一个小部件测试,它重现了您描述的错误:
import 'package:flutter/material.dart';
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);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: child,
);
}
}
错误信息如下,供引用:
Test failed. See exception logs above.
The test description was: Should test widget with http call
Warning: At least one test in this suite creates an HttpClient. When
running a test suite that uses TestWidgetsFlutterBinding, all HTTP
requests will return status code 400, and no network request will
actually be made. Any test expecting a real network connection and
status code will fail.
To test code that needs an HttpClient, provide your own HttpClient
implementation to the code under test, so that your test can
consistently provide a testable response to the code under test.
该错误告诉您问题所在:您不能在小部件测试中执行 HTTP 调用。因此,您需要模拟该 HTTP 调用,以便调用模拟而不是真正的 HTTP 调用。您可以使用许多选项来做到这一点,例如使用 mockito包。
这是使用 nock 的可能解决方案在 HTTP 级别模拟 HTTP 响应的包。
pubspec.yaml
:
dev_dependencies:
nock: ^1.1.2
小部件测试:
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')
.reply(200, json.encode('{"id": "49c23ebc-c107-4dae-b1c6-5d325b8f8b58", "name": "Example campus" }'));
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,
);
}
}
关于使用 HttpClient 进行 Flutter Widget 测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69248403/
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
我正在试验 jquery-ui 并查看和克隆一些示例。在一个示例(自动完成的组合框)中,我看到一个带有 ui-widget 类的 anchor (a) 元素,它与包含的 css 文件中的 .ui-wi
在我帮助维护的代码中,我发现了多个如下所示的代码示例: Description := IfThen(Assigned(Widget), Widget.Description, 'No Widget')
这个问题在这里已经有了答案: CSS Performance Question (8 个答案) 关闭 9 年前。 这是一个很常见的情况。假设我们有一些标记: 我们可以使用 2 个选项来
这个问题在这里已经有了答案: CSS: Class name selector- name starts with (2 个答案) 关闭 5 年前。
我有一个布局,其中Row小部件中有两个子部件,这两个都是灵活的小部件。左侧的小部件包含红色和蓝色的小部件,我希望根据右侧小部件的高度增加蓝色小部件的高度(这是一个灵活的小部件,其FLEX值为7)。。例
我有一个布局,其中Row小部件中有两个子部件,这两个都是灵活的小部件。左侧的小部件包含红色和蓝色的小部件,我希望根据右侧小部件的高度增加蓝色小部件的高度(这是一个灵活的小部件,其FLEX值为7)。。例
这是一个代码: import 'package:flutter/material.dart'; import 'package:flutterapp/ui/pages/notes_home.dart'
ListView、GridView、SingleChildScrollView 等小部件是可滚动的小部件,而Container、SizedBox, Column 不是。 有没有办法检查 Widget
假设我在 Python 中有这个简单的函数: def f(gender, name): if gender == 'male': return ranking_male(nam
我不想听起来像个糟糕的新手,但是小部件是独立的应用程序吗?例如,我正在为 Android 创建一个新闻阅读器应用程序,我想要一个主屏幕小部件。我是将小部件创建为 Hook 到其他应用程序的单独项目/应
如何告诉 Tk 小部件告诉我它的子级是什么(或谁,视情况而定)?有这个命令吗? 例如,给定一个带有标签、按钮和其他装饰的 Canvas 小部件 .cvs ...如何查询 Canvas ? 最佳答案 w
我为 Android 开发了一个 APP + 主屏幕小部件。现在我更新了应用程序(增加了版本代码/名称)但是当我安装时,它不会自动替换屏幕上现有的小部件。它只是说“问题加载小部件”。 有什么想法吗??
我是小部件开发的新手..我设法构建了一个无法调整大小的小部件..我希望它像 - 用户设法根据自己调整大小......有人可以告诉我如何制作它可能吗? 谢谢 friend 。 最佳答案 AppWidge
我有一个小部件列表: List widgetList = List(); widgetList.add(WidgetA()); widgetList.add(WidgetB()); widgetLis
对不起,我的英语不好! 我开发了一个今日小部件。我需要从小部件启动 map 应用程序(例如),并且在设备锁定时不工作。在这种情况下如何检测锁定的设备并启动解锁屏幕? 问候, 最佳答案 而不是使用 UI
我正在尝试制作我的小部件的免费版本,我想向小部件添加广告,这可能吗?如果是这样怎么办? 最佳答案 小部件应用程序中的 View 仅限于: 模拟时钟 按钮 天文台 图像按钮 ImageView 进度条
我在 Android Studio 中创建了一个新项目,然后添加了一个新的小部件并在我的 Nexus 5 5.1 上运行该应用程序,它可以工作,但是当尝试将小部件添加到主屏幕时,它没有出现在小部件列表
我有一个字符串 'currentMessage' 和一个用于显示它的标签。我有一个 Toplevel 小部件,其中包含一个文本小部件,为“currentMessage”提供新值: from tkint
我尝试使用这个 link 解决我的问题 update - I figured out that there is something wrong with the setter of the pend
我是一名优秀的程序员,十分优秀!