[英]Flutter Test Mock GraphQL Mutation result
我正在嘗試使用 GraphQL 為 Flutter 應用程序創建小部件測試。 我想要做的是測試應用程序的行為,這取決於 GraphQL Mutation 對用戶操作的結果。
這是該應用程序的一個非常簡單的示例:
class FirstScreen extends StatelessWidget {
@override
Widget return Container(
child: Mutation(
options: myMutationOptions,
onCompleted: (dynamic result) {
final bool myBool = result['bool'] as bool;
if (myBool) {
Navigator.of(context).push(MaterialPageRoute(builder: (context) => SecondScreen()));
} else {
Navigator.of(context).push(MaterialPageRoute(builder: (context) => ThirdScreen()));
}
},
builder: (RunMutation runMutation, QueryResult queryResult) {
return FlatButton(
child: Text('Button'),
onPressed: () async {
await runMutation(myParameters).networkResult;
},
);
},
),
);
}
我想要做的是模擬突變的結果,所以在我的小部件測試中,我可以測試按鈕重定向到SecondScreen
或ThirdScreen
取決於結果myBool
。
我怎樣才能做到這一點 ?
FirstScreen
包裝在FirstScreen
中,如下所示:class MockHttpClient extends Mock implements Client {}
group('Test mutation', () {
MockHttpClient mockHttpClient;
HttpLink httpLink;
ValueNotifier<GraphQLClient> client;
setUp(() async {
mockHttpClient = MockHttpClient();
httpLink = HttpLink(
uri: 'https://unused/graphql',
httpClient: mockHttpClient,
);
client = ValueNotifier(
GraphQLClient(
cache: InMemoryCache(storagePrefix: 'test'),
link: httpLink,
),
);
});
testWidgets('redirects to SecondScreen', (WidgetTester tester) async {
when(client.send(captureAny)).thenAnswer(/* ... */);
await tester.pumpWidget(GraphQLProvider(
client: client,
child: FirstScreen(),
));
// Click on button
verify(mockHttpClient.send(any)).called(1);
// etc.
});
})
我終於成功模擬了一個 GraphQL Mutation。 這是我如何做到的,它的靈感來自@Gpack 的評論,但我不得不為其添加一些修改和細節。
為了便於使用,我創建了一個包裝小部件GraphQLMutationMocker
:
class MockClient extends Mock implements Client {
MockClient({
this.mockedResult,
this.mockedStatus = 200,
});
final Map<String, dynamic> mockedResult;
final int mockedStatus;
@override
Future<StreamedResponse> send(BaseRequest request) {
return Future<StreamedResponse>.value(
StreamedResponse(
Stream.value(utf8.encode(jsonEncode(mockedResult))),
mockedStatus,
),
);
}
}
class GraphQLMutationMocker extends StatelessWidget {
const GraphQLMutationMocker({
@required this.child,
this.mockedResult = const {},
this.mockedStatus = 200,
this.url = 'http://url',
this.storagePrefix = 'test',
});
final Widget child;
final Map<String, dynamic> mockedResult;
final int mockedStatus;
final String url;
final String storagePrefix;
@override
Widget build(BuildContext context) {
final mockClient = MockClient(
mockedResult: mockedResult,
mockedStatus: mockedStatus,
);
final httpLink = HttpLink(
uri: url,
httpClient: mockClient,
);
final graphQLClient = ValueNotifier(
GraphQLClient(
cache: InMemoryCache(storagePrefix: storagePrefix),
link: httpLink,
),
);
return GraphQLProvider(
client: graphQLClient,
child: child,
);
}
}
然后很容易編寫測試
group('Test mutation', () {
testWidgets('It should redirect to SecondScreen', (WidgetTester tester) async {
await tester.pumpWidget(GraphQLMutationMocker(
mockedResult: <String, dynamic>{
'data': {
'bool': true,
},
},
child: FirstScreen(),
));
// Click on button
await tester.tap(find.text('Button'));
await tester.pumpAndSettle();
// Check I'm on the right screen
expect(find.byType(SecondScreen), findsOneWidget);
expect(find.byType(ThirdScreen), findsNothing);
});
testWidgets('It should redirect to ThirdScreen', (WidgetTester tester) async {
await tester.pumpWidget(GraphQLMutationMocker(
mockedResult: <String, dynamic>{
'data': {
'bool': false,
},
},
child: FirstScreen(),
));
// Click on button
await tester.tap(find.text('Button'));
await tester.pumpAndSettle();
// Check I'm on the right screen
expect(find.byType(SecondScreen), findsNothing);
expect(find.byType(ThirdScreen), findsOneWidget);
});
})
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.