Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mock 'google_maps_flutter' package for flutter tests?

I've recently started getting into flutter, but just as I was about to write a few widget tests, I noticed that I wasn't terribly sure how to mock out the Google Maps Flutter package.

Many examples I've seen include using the library "mockito" to mock out classes, but this assumes that the Google Maps widget will be injected into the widget to be tested. Unfortunately, with their given documentation and startup guide, this doesn't seem to be very possible:

class MapsDemo extends StatefulWidget {
  @override
  State createState() => MapsDemoState();
}

class MapsDemoState extends State<MapsDemo> {

  GoogleMapController mapController;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.all(15.0),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: <Widget>[
          Center(
            child: SizedBox(
              width: 300.0,
              height: 200.0,
              child: GoogleMap(
                onMapCreated: _onMapCreated,
              ),
            ),
          ),
          RaisedButton(
            child: const Text('Go to London'),
            onPressed: mapController == null ? null : () {
              mapController.animateCamera(CameraUpdate.newCameraPosition(
                const CameraPosition(
                  bearing: 270.0,
                  target: LatLng(51.5160895, -0.1294527),
                  tilt: 30.0,
                  zoom: 17.0,
                ),
              ));
            },
          ),
        ],
      ),
    );
  }

  void _onMapCreated(GoogleMapController controller) {
    setState(() { mapController = controller; });
  }
}

Note that the GoogleMaps widget cannot be passed in because onMapCreated is a required function, and that function relies private class method (give the parent widget access to GoogleMapsController). Many other examples of mockito mock functions that don't have this sort of callback function to set state.

There doesn't seem to be any other packages I've seen that can effectively mock out the GoogleMaps widget, so I don't really have any sort of example to follow. Ideally, what I was expecting was some sort of behavior like proxyquire or sinon in node.s (where you don't need to pass in the mocked libraries into function.constructors), but it looks like mockified classes need to be passed into the tested widgets.

Are there any other ideas on how to mock out this library for testing? Or should I just live with testing the actual functionality?

like image 268
john.zli Avatar asked Nov 17 '22 17:11

john.zli


1 Answers

I managed to mock the GoogleMaps by mocking the channels it uses:

setUpAll(() async {
  SystemChannels.platform_views.setMockMethodCallHandler((MethodCall call) {
    switch (call.method) {
      case 'create':
        return Future<int>.sync(() => 1);
      default:
        return Future<void>.sync(() {});
    }
  });

  MethodChannel('plugins.flutter.io/google_maps_0', StandardMethodCodec())
    .setMockMethodCallHandler((MethodCall methodCall) async {
      return null;
    });
}

I got inspiration from this webview plugin test (which is a PlatformView like the GoogleMaps widget), as well as this GoogleMaps plugin test

like image 196
ncuillery Avatar answered Dec 05 '22 20:12

ncuillery