Unverified Commit 886eb3e6 authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tools] remove mocks from ios_device, project, flutter_command test (#82195)

parent 191c75d4
......@@ -15,7 +15,7 @@ import 'package:flutter_tools/src/ios/devices.dart';
import 'package:flutter_tools/src/ios/ios_deploy.dart';
import 'package:flutter_tools/src/ios/mac.dart';
import 'package:flutter_tools/src/vmservice.dart';
import 'package:mockito/mockito.dart';
import 'package:test/fake.dart';
import 'package:vm_service/vm_service.dart';
import '../../src/common.dart';
......@@ -226,13 +226,13 @@ Runner(libsystem_asl.dylib)[297] <Notice>: libMobileGestalt
);
logReader.connectedVMService = vmService;
final MockIOSDeployDebugger iosDeployDebugger = MockIOSDeployDebugger();
when(iosDeployDebugger.debuggerAttached).thenReturn(true);
final FakeIOSDeployDebugger iosDeployDebugger = FakeIOSDeployDebugger();
iosDeployDebugger.debuggerAttached = true;
final Stream<String> debuggingLogs = Stream<String>.fromIterable(<String>[
'Message from debugger'
]);
when(iosDeployDebugger.logLines).thenAnswer((Invocation invocation) => debuggingLogs);
iosDeployDebugger.logLines = debuggingLogs;
logReader.debuggerStream = iosDeployDebugger;
// Wait for stream listeners to fire.
......@@ -260,8 +260,8 @@ Runner(libsystem_asl.dylib)[297] <Notice>: libMobileGestalt
),
useSyslog: false,
);
final MockIOSDeployDebugger iosDeployDebugger = MockIOSDeployDebugger();
when(iosDeployDebugger.logLines).thenAnswer((Invocation invocation) => debuggingLogs);
final FakeIOSDeployDebugger iosDeployDebugger = FakeIOSDeployDebugger();
iosDeployDebugger.logLines = debuggingLogs;
logReader.debuggerStream = iosDeployDebugger;
final Future<List<String>> logLines = logReader.logLines.toList();
......@@ -285,8 +285,8 @@ Runner(libsystem_asl.dylib)[297] <Notice>: libMobileGestalt
useSyslog: false,
);
final Completer<void> streamComplete = Completer<void>();
final MockIOSDeployDebugger iosDeployDebugger = MockIOSDeployDebugger();
when(iosDeployDebugger.logLines).thenAnswer((Invocation invocation) => debuggingLogs);
final FakeIOSDeployDebugger iosDeployDebugger = FakeIOSDeployDebugger();
iosDeployDebugger.logLines = debuggingLogs;
logReader.logLines.listen(null, onError: (Object error) => streamComplete.complete());
logReader.debuggerStream = iosDeployDebugger;
......@@ -303,14 +303,26 @@ Runner(libsystem_asl.dylib)[297] <Notice>: libMobileGestalt
),
useSyslog: false,
);
final MockIOSDeployDebugger iosDeployDebugger = MockIOSDeployDebugger();
when(iosDeployDebugger.logLines).thenAnswer((Invocation invocation) => const Stream<String>.empty());
final FakeIOSDeployDebugger iosDeployDebugger = FakeIOSDeployDebugger();
logReader.debuggerStream = iosDeployDebugger;
logReader.dispose();
verify(iosDeployDebugger.detach());
expect(iosDeployDebugger.detached, true);
});
});
}
class MockIOSDeployDebugger extends Mock implements IOSDeployDebugger {}
class FakeIOSDeployDebugger extends Fake implements IOSDeployDebugger {
bool detached = false;
@override
bool debuggerAttached = false;
@override
Stream<String> logLines = const Stream<String>.empty();
@override
void detach() {
detached = true;
}
}
......@@ -19,7 +19,7 @@ import 'package:flutter_tools/src/ios/plist_parser.dart';
import 'package:flutter_tools/src/ios/xcodeproj.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:meta/meta.dart';
import 'package:mockito/mockito.dart';
import 'package:test/fake.dart';
import '../src/common.dart';
import '../src/context.dart';
......@@ -397,16 +397,11 @@ apply plugin: 'kotlin-android'
testWithMocks('from build settings, if no plist', () async {
final FlutterProject project = await someProject();
project.ios.xcodeProject.createSync();
when(mockXcodeProjectInterpreter.getBuildSettings(any, buildContext: anyNamed('buildContext'))).thenAnswer(
(_) {
return Future<Map<String,String>>.value(<String, String>{
mockXcodeProjectInterpreter.buildSettings = <String, String>{
'PRODUCT_BUNDLE_IDENTIFIER': 'io.flutter.someProject',
});
}
);
when(mockXcodeProjectInterpreter.getInfo(any, projectFilename: anyNamed('projectFilename'))).thenAnswer( (_) {
return Future<XcodeProjectInfo>.value(XcodeProjectInfo(<String>[], <String>[], <String>['Runner'], logger));
});
};
mockXcodeProjectInterpreter.xcodeProjectInfo = XcodeProjectInfo(<String>[], <String>[], <String>['Runner'], logger);
expect(await project.ios.productBundleIdentifier(null), 'io.flutter.someProject');
});
......@@ -428,18 +423,12 @@ apply plugin: 'kotlin-android'
testWithMocks('from build settings and plist, if default variable', () async {
final FlutterProject project = await someProject();
project.ios.xcodeProject.createSync();
when(mockXcodeProjectInterpreter.getBuildSettings(any, buildContext: anyNamed('buildContext'))).thenAnswer(
(_) {
return Future<Map<String,String>>.value(<String, String>{
mockXcodeProjectInterpreter.buildSettings = <String, String>{
'PRODUCT_BUNDLE_IDENTIFIER': 'io.flutter.someProject',
});
}
);
when(mockXcodeProjectInterpreter.getInfo(any, projectFilename: anyNamed('projectFilename'))).thenAnswer( (_) {
return Future<XcodeProjectInfo>.value(XcodeProjectInfo(<String>[], <String>[], <String>['Runner'], logger));
});
};
mockXcodeProjectInterpreter.xcodeProjectInfo = XcodeProjectInfo(<String>[], <String>[], <String>['Runner'], logger);
testPlistUtils.setProperty('CFBundleIdentifier', r'$(PRODUCT_BUNDLE_IDENTIFIER)');
expect(await project.ios.productBundleIdentifier(null), 'io.flutter.someProject');
});
......@@ -447,28 +436,21 @@ apply plugin: 'kotlin-android'
final FlutterProject project = await someProject();
project.ios.xcodeProject.createSync();
project.ios.defaultHostInfoPlist.createSync(recursive: true);
when(mockXcodeProjectInterpreter.getBuildSettings(any, buildContext: anyNamed('buildContext'))).thenAnswer(
(_) {
return Future<Map<String,String>>.value(<String, String>{
mockXcodeProjectInterpreter.buildSettings = <String, String>{
'PRODUCT_BUNDLE_IDENTIFIER': 'io.flutter.someProject',
'SUFFIX': 'suffix',
});
}
);
when(mockXcodeProjectInterpreter.getInfo(any, projectFilename: anyNamed('projectFilename'))).thenAnswer( (_) {
return Future<XcodeProjectInfo>.value(XcodeProjectInfo(<String>[], <String>[], <String>['Runner'], logger));
});
};
mockXcodeProjectInterpreter.xcodeProjectInfo = XcodeProjectInfo(<String>[], <String>[], <String>['Runner'], logger);
testPlistUtils.setProperty('CFBundleIdentifier', r'$(PRODUCT_BUNDLE_IDENTIFIER).$(SUFFIX)');
expect(await project.ios.productBundleIdentifier(null), 'io.flutter.someProject.suffix');
});
testWithMocks('fails with no flavor and defined schemes', () async {
final FlutterProject project = await someProject();
project.ios.xcodeProject.createSync();
when(mockXcodeProjectInterpreter.getInfo(any, projectFilename: anyNamed('projectFilename'))).thenAnswer( (_) {
return Future<XcodeProjectInfo>.value(XcodeProjectInfo(<String>[], <String>[], <String>['free', 'paid'], logger));
});
mockXcodeProjectInterpreter.xcodeProjectInfo = XcodeProjectInfo(<String>[], <String>[], <String>['free', 'paid'], logger);
await expectToolExitLater(
project.ios.productBundleIdentifier(null),
contains('You must specify a --flavor option to select one of the available schemes.')
......@@ -478,29 +460,21 @@ apply plugin: 'kotlin-android'
testWithMocks('handles case insensitive flavor', () async {
final FlutterProject project = await someProject();
project.ios.xcodeProject.createSync();
when(mockXcodeProjectInterpreter.getBuildSettings(any, buildContext: anyNamed('buildContext'))).thenAnswer(
(_) {
return Future<Map<String,String>>.value(<String, String>{
mockXcodeProjectInterpreter.buildSettings = <String, String>{
'PRODUCT_BUNDLE_IDENTIFIER': 'io.flutter.someProject',
});
}
);
when(mockXcodeProjectInterpreter.getInfo(any, projectFilename: anyNamed('projectFilename'))).thenAnswer( (_) {
return Future<XcodeProjectInfo>.value(XcodeProjectInfo(<String>[], <String>[], <String>['Free'], logger));
});
};
mockXcodeProjectInterpreter.xcodeProjectInfo =XcodeProjectInfo(<String>[], <String>[], <String>['Free'], logger);
const BuildInfo buildInfo = BuildInfo(BuildMode.debug, 'free', treeShakeIcons: false);
expect(await project.ios.productBundleIdentifier(buildInfo), 'io.flutter.someProject');
});
testWithMocks('fails with flavor and default schemes', () async {
final FlutterProject project = await someProject();
project.ios.xcodeProject.createSync();
when(mockXcodeProjectInterpreter.getInfo(any, projectFilename: anyNamed('projectFilename'))).thenAnswer( (_) {
return Future<XcodeProjectInfo>.value(XcodeProjectInfo(<String>[], <String>[], <String>['Runner'], logger));
});
mockXcodeProjectInterpreter.xcodeProjectInfo = XcodeProjectInfo(<String>[], <String>[], <String>['Runner'], logger);
const BuildInfo buildInfo = BuildInfo(BuildMode.debug, 'free', treeShakeIcons: false);
await expectToolExitLater(
project.ios.productBundleIdentifier(buildInfo),
contains('The Xcode project does not define custom schemes. You cannot use the --flavor option.')
......@@ -514,6 +488,7 @@ apply plugin: 'kotlin-android'
});
expect(await project.ios.productBundleIdentifier(null), '');
});
testWithMocks('surrounded by double quotes', () async {
final FlutterProject project = await someProject();
addIosProjectFile(project.directory, projectFileContent: () {
......@@ -521,6 +496,7 @@ apply plugin: 'kotlin-android'
});
expect(await project.ios.productBundleIdentifier(null), 'io.flutter.someProject');
});
testWithMocks('surrounded by single quotes', () async {
final FlutterProject project = await someProject();
addIosProjectFile(project.directory, projectFileContent: () {
......@@ -550,14 +526,10 @@ apply plugin: 'kotlin-android'
testUsingContext('app product name xcodebuild settings', () async {
final FlutterProject project = await someProject();
project.ios.xcodeProject.createSync();
when(mockXcodeProjectInterpreter.getBuildSettings(any, buildContext: anyNamed('buildContext'))).thenAnswer((_) {
return Future<Map<String,String>>.value(<String, String>{
mockXcodeProjectInterpreter.buildSettings = <String, String>{
'FULL_PRODUCT_NAME': 'My App.app'
});
});
when(mockXcodeProjectInterpreter.getInfo(any, projectFilename: anyNamed('projectFilename'))).thenAnswer( (_) {
return Future<XcodeProjectInfo>.value(XcodeProjectInfo(<String>[], <String>[], <String>['Runner'], logger));
});
};
mockXcodeProjectInterpreter.xcodeProjectInfo = XcodeProjectInfo(<String>[], <String>[], <String>['Runner'], logger);
expect(await project.ios.hostAppBundleName(null), 'My App.app');
}, overrides: <Type, Generator>{
......@@ -667,16 +639,10 @@ apply plugin: 'kotlin-android'
group('with bundle identifier', () {
setUp(() {
when(mockXcodeProjectInterpreter.getBuildSettings(any, buildContext: anyNamed('buildContext'))).thenAnswer(
(_) {
return Future<Map<String,String>>.value(<String, String>{
mockXcodeProjectInterpreter.buildSettings = <String, String>{
'PRODUCT_BUNDLE_IDENTIFIER': 'io.flutter.someProject',
});
}
);
when(mockXcodeProjectInterpreter.getInfo(any, projectFilename: anyNamed('projectFilename'))).thenAnswer( (_) {
return Future<XcodeProjectInfo>.value(XcodeProjectInfo(<String>[], <String>[], <String>['Runner'], logger));
});
};
mockXcodeProjectInterpreter.xcodeProjectInfo = XcodeProjectInfo(<String>[], <String>[], <String>['Runner'], logger);
});
testUsingContext('no Info.plist in target', () async {
......@@ -1005,7 +971,23 @@ File androidPluginRegistrant(Directory parent) {
.childFile('GeneratedPluginRegistrant.java');
}
class MockXcodeProjectInterpreter extends Mock implements XcodeProjectInterpreter {
class MockXcodeProjectInterpreter extends Fake implements XcodeProjectInterpreter {
Map<String, String> buildSettings = <String, String>{};
XcodeProjectInfo xcodeProjectInfo;
@override
Future<Map<String, String>> getBuildSettings(String projectPath, {
XcodeProjectBuildContext buildContext,
Duration timeout = const Duration(minutes: 1),
}) async {
return buildSettings;
}
@override
Future<XcodeProjectInfo> getInfo(String projectPath, {String projectFilename}) async {
return xcodeProjectInfo;
}
@override
bool get isInstalled => true;
}
......@@ -21,7 +21,7 @@ import 'package:flutter_tools/src/dart/pub.dart';
import 'package:flutter_tools/src/globals_null_migrated.dart' as globals;
import 'package:flutter_tools/src/reporting/reporting.dart';
import 'package:flutter_tools/src/runner/flutter_command.dart';
import 'package:mockito/mockito.dart';
import 'package:test/fake.dart';
import '../../src/common.dart';
import '../../src/context.dart';
......@@ -30,19 +30,18 @@ import 'utils.dart';
void main() {
group('Flutter Command', () {
MockCache cache;
FakeCache cache;
TestUsage usage;
FakeClock clock;
MockProcessInfo mockProcessInfo;
FakeProcessInfo processInfo;
setUp(() {
Cache.disableLocking();
cache = MockCache();
cache = FakeCache();
usage = TestUsage();
clock = FakeClock();
mockProcessInfo = MockProcessInfo();
when(mockProcessInfo.maxRss).thenReturn(10);
processInfo = FakeProcessInfo();
processInfo.maxRss = 10;
});
tearDown(() {
......@@ -58,7 +57,8 @@ void main() {
testUsingContext('honors shouldUpdateCache false', () async {
final DummyFlutterCommand flutterCommand = DummyFlutterCommand(shouldUpdateCache: false);
await flutterCommand.run();
verifyNever(cache.updateAll(any));
expect(cache.artifacts, isEmpty);
expect(flutterCommand.deprecated, isFalse);
expect(flutterCommand.hidden, isFalse);
},
......@@ -71,7 +71,7 @@ void main() {
await flutterCommand.run();
// First call for universal, second for the rest
expect(
verify(cache.updateAll(captureAny)).captured,
cache.artifacts,
<Set<DevelopmentArtifact>>[
<DevelopmentArtifact>{DevelopmentArtifact.universal},
<DevelopmentArtifact>{},
......@@ -143,7 +143,7 @@ void main() {
void testUsingCommandContext(String testName, dynamic Function() testBody) {
testUsingContext(testName, testBody, overrides: <Type, Generator>{
ProcessInfo: () => mockProcessInfo,
ProcessInfo: () => processInfo,
SystemClock: () => clock,
Usage: () => usage,
});
......@@ -201,40 +201,6 @@ void main() {
]);
});
testUsingCommandContext('reports command that results in failure', () async {
// Crash if called a third time which is unexpected.
clock.times = <int>[1000, 2000];
final DummyFlutterCommand flutterCommand = DummyFlutterCommand(
commandFunction: () async {
return const FlutterCommandResult(ExitStatus.fail);
}
);
try {
await flutterCommand.run();
} on ToolExit {
verify(usage.sendCommand(
'dummy',
parameters: anyNamed('parameters'),
));
verify(usage.sendEvent(
'tool-command-result',
'dummy',
label: 'fail',
parameters: anyNamed('parameters'),
));
expect(verify(usage.sendEvent(
'tool-command-max-rss',
'dummy',
label: 'fail',
value: captureAnyNamed('value'),
)).captured[0],
10,
);
}
});
testUsingCommandContext('reports command that results in error', () async {
// Crash if called a third time which is unexpected.
clock.times = <int>[1000, 2000];
......@@ -315,15 +281,15 @@ void main() {
});
group('signals tests', () {
MockIoProcessSignal mockSignal;
FakeIoProcessSignal mockSignal;
ProcessSignal signalUnderTest;
StreamController<io.ProcessSignal> signalController;
setUp(() {
mockSignal = MockIoProcessSignal();
mockSignal = FakeIoProcessSignal();
signalUnderTest = ProcessSignal(mockSignal);
signalController = StreamController<io.ProcessSignal>();
when(mockSignal.watch()).thenAnswer((Invocation invocation) => signalController.stream);
mockSignal.stream = signalController.stream;
});
testUsingContext('reports command that is killed', () async {
......@@ -363,7 +329,7 @@ void main() {
),
]);
}, overrides: <Type, Generator>{
ProcessInfo: () => mockProcessInfo,
ProcessInfo: () => processInfo,
Signals: () => FakeSignals(
subForSigTerm: signalUnderTest,
exitSignals: <ProcessSignal>[signalUnderTest],
......@@ -397,11 +363,8 @@ void main() {
signalController.add(mockSignal);
await completer.future;
await globals.cache.lock();
globals.cache.releaseLock();
}, overrides: <Type, Generator>{
ProcessInfo: () => mockProcessInfo,
ProcessInfo: () => processInfo,
Signals: () => FakeSignals(
subForSigTerm: signalUnderTest,
exitSignals: <ProcessSignal>[signalUnderTest],
......@@ -671,8 +634,29 @@ class FakeDdsCommand extends FlutterCommand {
}
}
class MockProcessInfo extends Mock implements ProcessInfo {}
class MockIoProcessSignal extends Mock implements io.ProcessSignal {}
class FakeProcessInfo extends Fake implements ProcessInfo {
@override
int maxRss = 0;
}
class FakeIoProcessSignal extends Fake implements io.ProcessSignal {
Stream<io.ProcessSignal> stream;
@override
Stream<io.ProcessSignal> watch() => stream;
}
class FakeCache extends Fake implements Cache {
List<Set<DevelopmentArtifact>> artifacts = <Set<DevelopmentArtifact>>[];
@override
Future<void> updateAll(Set<DevelopmentArtifact> requiredArtifacts) async {
artifacts.add(requiredArtifacts.toSet());
}
@override
void releaseLock() { }
}
class FakeSignals implements Signals {
FakeSignals({
......@@ -708,8 +692,6 @@ class FakeClock extends Fake implements SystemClock {
}
}
class MockCache extends Mock implements Cache {}
class FakePub extends Fake implements Pub {
@override
Future<void> get({
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment