简体   繁体   English

Flutter 测试 Mock GraphQL 变异结果

[英]Flutter Test Mock GraphQL Mutation result

I'm trying to create widget tests for a flutter application using GraphQL.我正在尝试使用 GraphQL 为 Flutter 应用程序创建小部件测试。 What I want to do is to test the behaviour of the app which depends on the result of a GraphQL Mutation on a user action.我想要做的是测试应用程序的行为,这取决于 GraphQL Mutation 对用户操作的结果。

This is a very simple example of the app:这是该应用程序的一个非常简单的示例:

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;
         },
       );
      },
    ),
  );
}

What I would like to do is to mock the result of the mutation so in my widget tests, I can test that the button redirects to the SecondScreen or ThirdScreen depending of the result myBool .我想要做的是模拟突变的结果,所以在我的小部件测试中,我可以测试按钮重定向到SecondScreenThirdScreen取决于结果myBool

How can I do that ?我怎样才能做到这一点 ?

  1. Create a mock of http.Client like in the flutter docs像 flutter docs一样创建 http.Client 的模拟
  2. In your test, wrap your FirstScreen in a GraphqlProvider like so:在您的测试中,将您的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.
  });
})

I finally managed to successfully mock a GraphQL Mutation.我终于成功模拟了一个 GraphQL Mutation。 Here is how I did it, it is inspired from @Gpack's comment but I had to add some modifications and details to it.这是我如何做到的,它的灵感来自@Gpack 的评论,但我不得不为其添加一些修改和细节。

To make it easy to use I created a wrapper widget GraphQLMutationMocker :为了便于使用,我创建了一个包装小部件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,
    );
  }
}

Then it was pretty easy to write the tests然后很容易编写测试

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM