我正在测试我的自定义SearchDelegate
。测试示例将检查开始提供建议的字符数之后。
我写了两个示例测试,它们以某种方式相互影响。它们都是相同的,但是当我一起运行它们时,稍后出现在代码中的测试始终会失败。
在调试过程中,我发现FutureBuilder
方法中的buildSuggestions
不会等待searchEngine.search(query)
的将来完成,而只会在第二次测试中发生。
点击搜索图标后,我已经尝试过在内部添加test.runAsync
的{{1}}。另外,我简化了案例以使其更具可读性。
您可以在此处找到完整的代码:https://github.com/pmiara/search-delegate-test-fail 或在下面查看。
应用代码:
Future.delayed
测试文件:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class Entity {
final String value;
Entity.fromJson(Map<String, dynamic> json) : value = json['value'];
}
class MySearchDelegate extends SearchDelegate {
final MySearchEngine searchEngine;
MySearchDelegate({@required this.searchEngine});
@override
List<Widget> buildActions(BuildContext context) {
return [];
}
@override
Widget buildLeading(BuildContext context) {
return IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
close(context, null);
},
);
}
@override
Widget buildResults(BuildContext context) {
return FutureBuilder<List<Entity>>(
future: searchEngine.search(query),
builder: (BuildContext context, AsyncSnapshot<List<Entity>> snapshot) {
if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasData) {
final entities = snapshot.data;
return ListView.builder(
itemCount: entities.length,
itemBuilder: (context, index) => ListTile(
title: Text(entities[index].value),
onTap: () => close(context, entities[index]),
),
);
} else {
return Column();
}
},
);
}
@override
Widget buildSuggestions(BuildContext context) {
return FutureBuilder<List<Entity>>(
future: searchEngine.search(query),
builder: (BuildContext context, AsyncSnapshot<List<Entity>> snapshot) {
if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasData) {
final entities = snapshot.data;
return ListView.builder(
itemCount: entities.length,
itemBuilder: (context, index) => ListTile(
title: Text(entities[index].value),
onTap: () {
query = entities[index].value;
showResults(context);
},
),
);
} else {
return Column();
}
},
);
}
}
class MySearchEngine {
Future<List<Entity>> search(String query) async {
final jsonEntities =
await rootBundle.loadString('test_resources/entities.json');
final entities = jsonDecode(jsonEntities)
.map<Entity>((json) => Entity.fromJson(json))
.toList();
return entities;
}
}
class TestHomePage extends StatelessWidget {
final MySearchDelegate delegate;
const TestHomePage({@required this.delegate});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Builder(
builder: (BuildContext context) {
return Scaffold(
body: Center(
child: IconButton(
icon: Icon(Icons.search),
onPressed: () async {
showSearch(
context: context,
delegate: delegate,
);
},
),
),
);
},
),
);
}
}
/// Run to see what tests should "see"
void main() => runApp(
TestHomePage(
delegate: MySearchDelegate(
searchEngine: MySearchEngine(),
),
),
);
pubsec.yaml:
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:search_delegate_test/search_delegate_problem.dart';
void main() {
testWidgets('First test', (WidgetTester tester) async {
final delegate = MySearchDelegate(
searchEngine: MySearchEngine(),
);
await tester.pumpWidget(
TestHomePage(
delegate: delegate,
),
);
await tester.tap(find.byIcon(Icons.search));
await tester.pumpAndSettle();
await tester.enterText(find.byType(TextField), 'query');
await tester.pumpAndSettle();
expect(find.byType(ListTile), findsNWidgets(3));
});
testWidgets('Second test', (WidgetTester tester) async {
final delegate = MySearchDelegate(
searchEngine: MySearchEngine(),
);
await tester.pumpWidget(
TestHomePage(
delegate: delegate,
),
);
await tester.tap(find.byIcon(Icons.search));
await tester.pumpAndSettle();
await tester.enterText(find.byType(TextField), 'query');
await tester.pumpAndSettle();
expect(find.byType(ListTile), findsNWidgets(3));
});
}
test_resources / entities.json:
name: search_delegate_test
description: A new Flutter application.
version: 1.0.0+1
environment:
sdk: ">=2.2.2 <3.0.0"
dependencies:
flutter:
sdk: flutter
dev_dependencies:
flutter_test:
sdk: flutter
test: any
flutter:
assets:
- test_resources/
uses-material-design: true
[
{
"value": "abc"
},
{
"value": "abc123"
},
{
"value": "123def"
}
]
的结果(我正在使用Android Studio)
flutter doctor
我得到的错误:
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, v1.7.8+hotfix.4, on Linux, locale pl_PL.UTF-8)
[✓] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
[✓] Android Studio (version 3.4)
[!] IntelliJ IDEA Ultimate Edition (version 2019.1)
✗ Flutter plugin not installed; this adds Flutter specific functionality.
✗ Dart plugin not installed; this adds Dart specific functionality.
[!] IntelliJ IDEA Community Edition (version 2019.1)
✗ Flutter plugin not installed; this adds Flutter specific functionality.
✗ Dart plugin not installed; this adds Dart specific functionality.
[✓] Connected device (1 available)
! Doctor found issues in 2 categories.