Skip to content

Commit b90e42b

Browse files
[url_launcher] Migrate unit tests to NNBD (flutter#3657)
Replaces the problematic Mockito mock with a manual mock that handles null and non-null types correctly. Removes the unit test of the example app, since it's not adding any actual coverage.
1 parent 8464890 commit b90e42b

File tree

5 files changed

+314
-250
lines changed

5 files changed

+314
-250
lines changed

packages/url_launcher/url_launcher/example/test/url_launcher_example_test.dart

Lines changed: 0 additions & 52 deletions
This file was deleted.

packages/url_launcher/url_launcher/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ dev_dependencies:
3939
flutter_test:
4040
sdk: flutter
4141
test: ^1.16.3
42-
mockito: ^5.0.0-nullsafety.7
42+
mockito: ^5.0.0
4343
plugin_platform_interface: ^2.0.0
4444
pedantic: ^1.10.0
4545

packages/url_launcher/url_launcher/test/link_test.dart

Lines changed: 53 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,26 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
// TODO(egarciad): Remove once Mockito has been migrated to null safety.
6-
// @dart = 2.9
7-
85
import 'dart:ui';
6+
97
import 'package:flutter/material.dart';
108
import 'package:flutter_test/flutter_test.dart';
119
import 'package:mockito/mockito.dart';
1210
import 'package:flutter/services.dart';
13-
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
1411
import 'package:url_launcher/link.dart';
1512
import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart';
1613

14+
import 'mock_url_launcher_platform.dart';
15+
1716
final MethodCodec _codec = const JSONMethodCodec();
1817

1918
void main() {
20-
final MockUrlLauncher mock = MockUrlLauncher();
21-
UrlLauncherPlatform.instance = mock;
19+
late MockUrlLauncher mock;
2220

23-
PlatformMessageCallback realOnPlatformMessage;
21+
PlatformMessageCallback? realOnPlatformMessage;
2422
setUp(() {
23+
mock = MockUrlLauncher();
24+
UrlLauncherPlatform.instance = mock;
2525
realOnPlatformMessage = window.onPlatformMessage;
2626
});
2727
tearDown(() {
@@ -31,11 +31,11 @@ void main() {
3131
group('$Link', () {
3232
testWidgets('handles null uri correctly', (WidgetTester tester) async {
3333
bool isBuilt = false;
34-
FollowLink followLink;
34+
FollowLink? followLink;
3535

3636
final Link link = Link(
3737
uri: null,
38-
builder: (BuildContext context, FollowLink followLink2) {
38+
builder: (BuildContext context, FollowLink? followLink2) {
3939
isBuilt = true;
4040
followLink = followLink2;
4141
return Container();
@@ -50,66 +50,62 @@ void main() {
5050

5151
testWidgets('calls url_launcher for external URLs with blank target',
5252
(WidgetTester tester) async {
53-
FollowLink followLink;
53+
FollowLink? followLink;
5454

5555
await tester.pumpWidget(Link(
5656
uri: Uri.parse('http://example.com/foobar'),
5757
target: LinkTarget.blank,
58-
builder: (BuildContext context, FollowLink followLink2) {
58+
builder: (BuildContext context, FollowLink? followLink2) {
5959
followLink = followLink2;
6060
return Container();
6161
},
6262
));
6363

64-
when(mock.canLaunch('http://example.com/foobar'))
65-
.thenAnswer((realInvocation) => Future<bool>.value(true));
66-
clearInteractions(mock);
67-
await followLink();
68-
69-
verifyInOrder([
70-
mock.canLaunch('http://example.com/foobar'),
71-
mock.launch(
72-
'http://example.com/foobar',
64+
mock
65+
..setLaunchExpectations(
66+
url: 'http://example.com/foobar',
7367
useSafariVC: false,
7468
useWebView: false,
7569
universalLinksOnly: false,
7670
enableJavaScript: false,
7771
enableDomStorage: false,
7872
headers: <String, String>{},
73+
webOnlyWindowName: null,
7974
)
80-
]);
75+
..setResponse(true);
76+
await followLink!();
77+
expect(mock.canLaunchCalled, isTrue);
78+
expect(mock.launchCalled, isTrue);
8179
});
8280

8381
testWidgets('calls url_launcher for external URLs with self target',
8482
(WidgetTester tester) async {
85-
FollowLink followLink;
83+
FollowLink? followLink;
8684

8785
await tester.pumpWidget(Link(
8886
uri: Uri.parse('http://example.com/foobar'),
8987
target: LinkTarget.self,
90-
builder: (BuildContext context, FollowLink followLink2) {
88+
builder: (BuildContext context, FollowLink? followLink2) {
9189
followLink = followLink2;
9290
return Container();
9391
},
9492
));
9593

96-
when(mock.canLaunch('http://example.com/foobar'))
97-
.thenAnswer((realInvocation) => Future<bool>.value(true));
98-
clearInteractions(mock);
99-
await followLink();
100-
101-
verifyInOrder([
102-
mock.canLaunch('http://example.com/foobar'),
103-
mock.launch(
104-
'http://example.com/foobar',
94+
mock
95+
..setLaunchExpectations(
96+
url: 'http://example.com/foobar',
10597
useSafariVC: true,
10698
useWebView: true,
10799
universalLinksOnly: false,
108100
enableJavaScript: false,
109101
enableDomStorage: false,
110102
headers: <String, String>{},
103+
webOnlyWindowName: null,
111104
)
112-
]);
105+
..setResponse(true);
106+
await followLink!();
107+
expect(mock.canLaunchCalled, isTrue);
108+
expect(mock.launchCalled, isTrue);
113109
});
114110

115111
testWidgets('sends navigation platform messages for internal route names',
@@ -125,21 +121,21 @@ void main() {
125121
final List<MethodCall> frameworkCalls = <MethodCall>[];
126122
window.onPlatformMessage = (
127123
String name,
128-
ByteData data,
129-
PlatformMessageResponseCallback callback,
124+
ByteData? data,
125+
PlatformMessageResponseCallback? callback,
130126
) {
131127
frameworkCalls.add(_codec.decodeMethodCall(data));
132-
realOnPlatformMessage(name, data, callback);
128+
realOnPlatformMessage!(name, data, callback);
133129
};
134130

135131
final Uri uri = Uri.parse('/foo/bar');
136-
FollowLink followLink;
132+
FollowLink? followLink;
137133

138134
await tester.pumpWidget(MaterialApp(
139135
routes: <String, WidgetBuilder>{
140136
'/': (BuildContext context) => Link(
141137
uri: uri,
142-
builder: (BuildContext context, FollowLink followLink2) {
138+
builder: (BuildContext context, FollowLink? followLink2) {
143139
followLink = followLink2;
144140
return Container();
145141
},
@@ -150,11 +146,11 @@ void main() {
150146

151147
engineCalls.clear();
152148
frameworkCalls.clear();
153-
clearInteractions(mock);
154-
await followLink();
149+
await followLink!();
155150

156151
// Shouldn't use url_launcher when uri is an internal route name.
157-
verifyZeroInteractions(mock);
152+
expect(mock.canLaunchCalled, isFalse);
153+
expect(mock.launchCalled, isFalse);
158154

159155
// A message should've been sent to the engine (by the Navigator, not by
160156
// the Link widget).
@@ -191,19 +187,19 @@ void main() {
191187
final List<MethodCall> frameworkCalls = <MethodCall>[];
192188
window.onPlatformMessage = (
193189
String name,
194-
ByteData data,
195-
PlatformMessageResponseCallback callback,
190+
ByteData? data,
191+
PlatformMessageResponseCallback? callback,
196192
) {
197193
frameworkCalls.add(_codec.decodeMethodCall(data));
198-
realOnPlatformMessage(name, data, callback);
194+
realOnPlatformMessage!(name, data, callback);
199195
};
200196

201197
final Uri uri = Uri.parse('/foo/bar');
202-
FollowLink followLink;
198+
FollowLink? followLink;
203199

204200
final Link link = Link(
205201
uri: uri,
206-
builder: (BuildContext context, FollowLink followLink2) {
202+
builder: (BuildContext context, FollowLink? followLink2) {
207203
followLink = followLink2;
208204
return Container();
209205
},
@@ -217,11 +213,11 @@ void main() {
217213

218214
engineCalls.clear();
219215
frameworkCalls.clear();
220-
clearInteractions(mock);
221-
await followLink();
216+
await followLink!();
222217

223218
// Shouldn't use url_launcher when uri is an internal route name.
224-
verifyZeroInteractions(mock);
219+
expect(mock.canLaunchCalled, isFalse);
220+
expect(mock.launchCalled, isFalse);
225221

226222
// Sends route information update to the engine.
227223
expect(engineCalls, hasLength(1));
@@ -249,10 +245,6 @@ void main() {
249245
});
250246
}
251247

252-
class MockUrlLauncher extends Mock
253-
with MockPlatformInterfaceMixin
254-
implements UrlLauncherPlatform {}
255-
256248
class MockRouteInformationParser extends Mock
257249
implements RouteInformationParser<bool> {
258250
@override
@@ -261,13 +253,19 @@ class MockRouteInformationParser extends Mock
261253
}
262254
}
263255

264-
class MockRouterDelegate extends Mock implements RouterDelegate {
265-
MockRouterDelegate({@required this.builder});
256+
class MockRouterDelegate extends Mock implements RouterDelegate<Object> {
257+
MockRouterDelegate({required this.builder});
266258

267259
final WidgetBuilder builder;
268260

269261
@override
270262
Widget build(BuildContext context) {
271263
return builder(context);
272264
}
265+
266+
@override
267+
Future<void> setInitialRoutePath(Object configuration) async {}
268+
269+
@override
270+
Future<void> setNewRoutePath(Object configuration) async {}
273271
}

0 commit comments

Comments
 (0)