[flutter_tools] remove globals from compile and devices (#67485)

Remove global variables from compile.dart and devices.dart (except for dds which needs more changes).

#47161
diff --git a/packages/flutter_tools/lib/src/base/terminal.dart b/packages/flutter_tools/lib/src/base/terminal.dart
index 6bf4b20..969bca7 100644
--- a/packages/flutter_tools/lib/src/base/terminal.dart
+++ b/packages/flutter_tools/lib/src/base/terminal.dart
@@ -96,6 +96,14 @@
   bool get usesTerminalUi;
   set usesTerminalUi(bool value);
 
+  /// Whether there is a terminal attached to stdin.
+  ///
+  /// If true, this usually indicates that a user is using the CLI as
+  /// opposed to using an IDE. This can be used to determine
+  /// whether it is appropriate to show a terminal prompt,
+  /// or whether an automatic selection should be made instead.
+  bool get stdinHasTerminal;
+
   String bolden(String message);
 
   String color(String message, TerminalColor color);
@@ -251,6 +259,9 @@
     }
   }
 
+  @override
+  bool get stdinHasTerminal => _stdio.stdinHasTerminal;
+
   Stream<String> _broadcastStdInString;
 
   @override
@@ -339,4 +350,7 @@
 
   @override
   bool get supportsEmoji => false;
+
+  @override
+  bool get stdinHasTerminal => false;
 }
diff --git a/packages/flutter_tools/lib/src/commands/devices.dart b/packages/flutter_tools/lib/src/commands/devices.dart
index a5a5060..59829b3 100644
--- a/packages/flutter_tools/lib/src/commands/devices.dart
+++ b/packages/flutter_tools/lib/src/commands/devices.dart
@@ -80,7 +80,7 @@
         globals.printStatus(status.toString());
       } else {
         globals.printStatus('${devices.length} connected ${pluralize('device', devices.length)}:\n');
-        await Device.printDevices(devices);
+        await Device.printDevices(devices, globals.logger);
       }
       await _printDiagnostics();
     }
diff --git a/packages/flutter_tools/lib/src/commands/drive.dart b/packages/flutter_tools/lib/src/commands/drive.dart
index 7fa8e81..ebc9b77 100644
--- a/packages/flutter_tools/lib/src/commands/drive.dart
+++ b/packages/flutter_tools/lib/src/commands/drive.dart
@@ -427,7 +427,7 @@
     }
     if (devices.length > 1) {
       globals.printStatus("Found ${devices.length} devices with name or id matching '${deviceManager.specifiedDeviceId}':");
-      await Device.printDevices(devices);
+      await Device.printDevices(devices, globals.logger);
       return null;
     }
     return devices.first;
@@ -438,7 +438,7 @@
     return null;
   } else if (devices.length > 1) {
     globals.printStatus('Found multiple connected devices:');
-    await Device.printDevices(devices);
+    await Device.printDevices(devices, globals.logger);
   }
   globals.printStatus('Using device ${devices.first.name}.');
   return devices.first;
diff --git a/packages/flutter_tools/lib/src/compile.dart b/packages/flutter_tools/lib/src/compile.dart
index 138fb0e..770286b 100644
--- a/packages/flutter_tools/lib/src/compile.dart
+++ b/packages/flutter_tools/lib/src/compile.dart
@@ -17,7 +17,6 @@
 import 'base/platform.dart';
 import 'build_info.dart';
 import 'convert.dart';
-import 'globals.dart' as globals;
 
 /// The target model describes the set of core libraries that are available within
 /// the SDK.
@@ -416,8 +415,6 @@
     List<String> dartDefines,
     String librariesSpec,
     @required Platform platform,
-    // Deprecated
-    List<String> experimentalFlags,
   }) = DefaultResidentCompiler;
 
   // TODO(jonahwilliams): find a better way to configure additional file system
@@ -517,12 +514,10 @@
     this.platformDill,
     List<String> dartDefines,
     this.librariesSpec,
-    // Deprecated
-    List<String> experimentalFlags, // ignore: avoid_unused_constructor_parameters
   }) : assert(sdkRoot != null),
-       _logger = logger ?? globals.logger,
-       _processManager = processManager ?? globals.processManager,
-       _artifacts = artifacts ?? globals.artifacts,
+       _logger = logger,
+       _processManager = processManager,
+       _artifacts = artifacts,
        _stdoutHandler = StdoutHandler(logger: logger),
        _platform = platform,
        dartDefines = dartDefines ?? const <String>[],
diff --git a/packages/flutter_tools/lib/src/context_runner.dart b/packages/flutter_tools/lib/src/context_runner.dart
index 50d3dbe..8d8fa83 100644
--- a/packages/flutter_tools/lib/src/context_runner.dart
+++ b/packages/flutter_tools/lib/src/context_runner.dart
@@ -152,6 +152,7 @@
           featureFlags: featureFlags,
         ),
         operatingSystemUtils: globals.os,
+        terminal: globals.terminal,
       ),
       Doctor: () => Doctor(logger: globals.logger),
       DoctorValidatorsProvider: () => DoctorValidatorsProvider.defaultInstance,
diff --git a/packages/flutter_tools/lib/src/device.dart b/packages/flutter_tools/lib/src/device.dart
index 92d4ebf..71a71c4 100644
--- a/packages/flutter_tools/lib/src/device.dart
+++ b/packages/flutter_tools/lib/src/device.dart
@@ -23,14 +23,15 @@
 import 'base/logger.dart';
 import 'base/os.dart';
 import 'base/platform.dart';
-import 'base/user_messages.dart';
+import 'base/terminal.dart';
+import 'base/user_messages.dart' hide userMessages;
 import 'base/utils.dart';
 import 'build_info.dart';
 import 'features.dart';
 import 'fuchsia/fuchsia_device.dart';
 import 'fuchsia/fuchsia_sdk.dart';
 import 'fuchsia/fuchsia_workflow.dart';
-import 'globals.dart' as globals;
+import 'globals.dart' as globals show logger;
 import 'ios/devices.dart';
 import 'ios/ios_workflow.dart';
 import 'ios/simulators.dart';
@@ -81,6 +82,17 @@
 
 /// A disovery mechanism for flutter-supported development devices.
 abstract class DeviceManager {
+  DeviceManager({
+    @required Logger logger,
+    @required Terminal terminal,
+    @required UserMessages userMessages,
+  }) : _logger = logger,
+       _terminal = terminal,
+       _userMessages = userMessages;
+
+  final Logger _logger;
+  final Terminal _terminal;
+  final UserMessages _userMessages;
 
   /// Constructing DeviceManagers is cheap; they only do expensive work if some
   /// of their methods are called.
@@ -139,7 +151,7 @@
           return null;
         }, onError: (dynamic error, StackTrace stackTrace) {
           // Return matches from other discoverers even if one fails.
-          globals.printTrace('Ignored error discovering $deviceId: $error');
+          _logger.printTrace('Ignored error discovering $deviceId: $error');
         })
     ];
 
@@ -275,11 +287,11 @@
       // has two active Android devices running, then we request the user to
       // choose one. If the user has two nonEphemeral devices running, we also
       // request input to choose one.
-      if (devices.length > 1 && globals.stdio.stdinHasTerminal) {
-        globals.printStatus(globals.userMessages.flutterMultipleDevicesFound);
-        await Device.printDevices(devices);
+      if (devices.length > 1 && _terminal.stdinHasTerminal) {
+        _logger.printStatus(_userMessages.flutterMultipleDevicesFound);
+        await Device.printDevices(devices, _logger);
         final Device chosenDevice = await _chooseOneOfAvailableDevices(devices);
-        globals.deviceManager.specifiedDeviceId = chosenDevice.id;
+        specifiedDeviceId = chosenDevice.id;
         devices = <Device>[chosenDevice];
       }
     }
@@ -298,18 +310,19 @@
   void _displayDeviceOptions(List<Device> devices) {
     int count = 0;
     for (final Device device in devices) {
-      globals.printStatus(userMessages.flutterChooseDevice(count, device.name, device.id));
+      _logger.printStatus(_userMessages.flutterChooseDevice(count, device.name, device.id));
       count++;
     }
   }
 
   Future<String> _readUserInput(int deviceCount) async {
-    globals.terminal.usesTerminalUi = true;
-    final String result = await globals.terminal.promptForCharInput(
-        <String>[ for (int i = 0; i < deviceCount; i++) '$i', 'q', 'Q'],
-        displayAcceptedCharacters: false,
-        logger: globals.logger,
-        prompt: userMessages.flutterChooseOne);
+    _terminal.usesTerminalUi = true;
+    final String result = await _terminal.promptForCharInput(
+      <String>[ for (int i = 0; i < deviceCount; i++) '$i', 'q', 'Q'],
+      displayAcceptedCharacters: false,
+      logger: _logger,
+      prompt: _userMessages.flutterChooseOne,
+    );
     return result;
   }
 
@@ -345,6 +358,7 @@
     @required UserMessages userMessages,
     @required OperatingSystemUtils operatingSystemUtils,
     @required WindowsWorkflow windowsWorkflow,
+    @required Terminal terminal,
   }) : deviceDiscoverers =  <DeviceDiscovery>[
     AndroidDevices(
       logger: logger,
@@ -408,7 +422,11 @@
       processManager: processManager,
       logger: logger,
     ),
-  ];
+  ], super(
+      logger: logger,
+      terminal: terminal,
+      userMessages: userMessages,
+    );
 
   @override
   final List<DeviceDiscovery> deviceDiscoverers;
@@ -465,7 +483,7 @@
         final List<Device> devices = await pollingGetDevices(timeout: pollingTimeout);
         deviceNotifier.updateWithNewList(devices);
       } on TimeoutException {
-        globals.printTrace('Device poll timed out. Will retry.');
+        // Do nothing on a timeout.
       }
       // Subsequent timeouts after initial population should wait longer.
       _timer = _initTimer(_pollingTimeout);
@@ -736,8 +754,8 @@
     }
   }
 
-  static Future<void> printDevices(List<Device> devices) async {
-    await descriptions(devices).forEach(globals.printStatus);
+  static Future<void> printDevices(List<Device> devices, Logger logger) async {
+    await descriptions(devices).forEach(logger.printStatus);
   }
 
   static List<String> devicesPlatformTypes(List<Device> devices) {
diff --git a/packages/flutter_tools/lib/src/runner/flutter_command.dart b/packages/flutter_tools/lib/src/runner/flutter_command.dart
index 7003262..0c0d61a 100644
--- a/packages/flutter_tools/lib/src/runner/flutter_command.dart
+++ b/packages/flutter_tools/lib/src/runner/flutter_command.dart
@@ -1063,7 +1063,7 @@
         devices = await deviceManager.getAllConnectedDevices();
       }
       globals.printStatus('');
-      await Device.printDevices(devices);
+      await Device.printDevices(devices, globals.logger);
       return null;
     }
     return devices;
@@ -1087,7 +1087,7 @@
       globals.printStatus(userMessages.flutterSpecifyDevice);
       deviceList = await globals.deviceManager.getAllConnectedDevices();
       globals.printStatus('');
-      await Device.printDevices(deviceList);
+      await Device.printDevices(deviceList, globals.logger);
       return null;
     }
     return deviceList.single;
diff --git a/packages/flutter_tools/test/general.shard/device_test.dart b/packages/flutter_tools/test/general.shard/device_test.dart
index 5067cdf..1331d18 100644
--- a/packages/flutter_tools/test/general.shard/device_test.dart
+++ b/packages/flutter_tools/test/general.shard/device_test.dart
@@ -5,15 +5,13 @@
 import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/base/logger.dart';
 import 'package:flutter_tools/src/base/terminal.dart';
-import 'package:flutter_tools/src/artifacts.dart';
+import 'package:flutter_tools/src/base/user_messages.dart';
 import 'package:flutter_tools/src/build_info.dart';
-import 'package:flutter_tools/src/cache.dart';
 import 'package:flutter_tools/src/device.dart';
-import 'package:flutter_tools/src/base/io.dart';
 import 'package:flutter_tools/src/project.dart';
+import 'package:meta/meta.dart';
 import 'package:mockito/mockito.dart';
 import 'package:fake_async/fake_async.dart';
-import 'package:flutter_tools/src/globals.dart' as globals;
 
 import '../src/common.dart';
 import '../src/context.dart';
@@ -21,32 +19,28 @@
 import '../src/mocks.dart';
 
 void main() {
-  Cache cache;
-  BufferLogger logger;
-
-  setUp(() {
-    cache = Cache.test();
-    logger = BufferLogger.test();
-  });
-
   group('DeviceManager', () {
-    testUsingContext('getDevices', () async {
+    testWithoutContext('getDevices', () async {
       final FakeDevice device1 = FakeDevice('Nexus 5', '0553790d0a4e726f');
       final FakeDevice device2 = FakeDevice('Nexus 5X', '01abfc49119c410e');
       final FakeDevice device3 = FakeDevice('iPod touch', '82564b38861a9a5');
       final List<Device> devices = <Device>[device1, device2, device3];
-      final DeviceManager deviceManager = TestDeviceManager(devices);
+
+      final DeviceManager deviceManager = TestDeviceManager(
+        devices,
+        logger: BufferLogger.test(),
+        terminal: Terminal.test(),
+      );
+
       expect(await deviceManager.getDevices(), devices);
-    }, overrides: <Type, Generator>{
-      Artifacts: () => Artifacts.test(),
-      Cache: () => cache,
     });
 
-    testUsingContext('getDeviceById exact matcher', () async {
+    testWithoutContext('getDeviceById exact matcher', () async {
       final FakeDevice device1 = FakeDevice('Nexus 5', '0553790d0a4e726f');
       final FakeDevice device2 = FakeDevice('Nexus 5X', '01abfc49119c410e');
       final FakeDevice device3 = FakeDevice('iPod touch', '82564b38861a9a5');
       final List<Device> devices = <Device>[device1, device2, device3];
+      final BufferLogger logger = BufferLogger.test();
 
       // Include different device discoveries:
       // 1. One that never completes to prove the first exact match is
@@ -60,6 +54,8 @@
           ThrowingPollingDeviceDiscovery(),
           LongPollingDeviceDiscovery(),
         ],
+        logger: logger,
+        terminal: Terminal.test(),
       );
 
       Future<void> expectDevice(String id, List<Device> expected) async {
@@ -71,17 +67,14 @@
       expect(logger.traceText, contains('Ignored error discovering Nexus 5X'));
       await expectDevice('0553790d0a4e726f', <Device>[device1]);
       expect(logger.traceText, contains('Ignored error discovering 0553790d0a4e726f'));
-    }, overrides: <Type, Generator>{
-      Artifacts: () => Artifacts.test(),
-      Cache: () => cache,
-      Logger: () => logger,
     });
 
-    testUsingContext('getDeviceById prefix matcher', () async {
+    testWithoutContext('getDeviceById prefix matcher', () async {
       final FakeDevice device1 = FakeDevice('Nexus 5', '0553790d0a4e726f');
       final FakeDevice device2 = FakeDevice('Nexus 5X', '01abfc49119c410e');
       final FakeDevice device3 = FakeDevice('iPod touch', '82564b38861a9a5');
       final List<Device> devices = <Device>[device1, device2, device3];
+      final BufferLogger logger = BufferLogger.test();
 
       // Include different device discoveries:
       // 1. One that throws, to prove matches can return when some succeed
@@ -92,6 +85,8 @@
         deviceDiscoveryOverrides: <DeviceDiscovery>[
           ThrowingPollingDeviceDiscovery(),
         ],
+        logger: logger,
+        terminal: Terminal.test(),
       );
 
       Future<void> expectDevice(String id, List<Device> expected) async {
@@ -103,86 +98,67 @@
       expect(logger.traceText, contains('Ignored error discovering 0553790'));
       await expectDevice('Nexus', <Device>[device1, device2]);
       expect(logger.traceText, contains('Ignored error discovering Nexus'));
-    }, overrides: <Type, Generator>{
-      Artifacts: () => Artifacts.test(),
-      Cache: () => cache,
-      Logger: () => logger,
     });
 
-    testUsingContext('getAllConnectedDevices caches', () async {
+    testWithoutContext('getAllConnectedDevices caches', () async {
       final FakeDevice device1 = FakeDevice('Nexus 5', '0553790d0a4e726f');
-      final TestDeviceManager deviceManager = TestDeviceManager(<Device>[device1]);
+      final TestDeviceManager deviceManager = TestDeviceManager(
+        <Device>[device1],
+        logger: BufferLogger.test(),
+        terminal: Terminal.test(),
+      );
       expect(await deviceManager.getAllConnectedDevices(), <Device>[device1]);
 
       final FakeDevice device2 = FakeDevice('Nexus 5X', '01abfc49119c410e');
       deviceManager.resetDevices(<Device>[device2]);
       expect(await deviceManager.getAllConnectedDevices(), <Device>[device1]);
-    }, overrides: <Type, Generator>{
-      Artifacts: () => Artifacts.test(),
-      Cache: () => cache,
     });
 
-    testUsingContext('refreshAllConnectedDevices does not cache', () async {
+    testWithoutContext('refreshAllConnectedDevices does not cache', () async {
       final FakeDevice device1 = FakeDevice('Nexus 5', '0553790d0a4e726f');
-      final TestDeviceManager deviceManager = TestDeviceManager(<Device>[device1]);
+      final TestDeviceManager deviceManager = TestDeviceManager(
+        <Device>[device1],
+        logger: BufferLogger.test(),
+        terminal: Terminal.test(),
+      );
       expect(await deviceManager.refreshAllConnectedDevices(), <Device>[device1]);
 
       final FakeDevice device2 = FakeDevice('Nexus 5X', '01abfc49119c410e');
       deviceManager.resetDevices(<Device>[device2]);
       expect(await deviceManager.refreshAllConnectedDevices(), <Device>[device2]);
-    }, overrides: <Type, Generator>{
-      Artifacts: () => Artifacts.test(),
-      Cache: () => cache,
     });
   });
 
-  group('PollingDeviceDiscovery', () {
-    testUsingContext('startPolling', () {
-      FakeAsync().run((FakeAsync time) {
-        final FakePollingDeviceDiscovery pollingDeviceDiscovery = FakePollingDeviceDiscovery();
-        pollingDeviceDiscovery.startPolling();
-        time.elapse(const Duration(milliseconds: 4001));
+  testWithoutContext('PollingDeviceDiscovery startPolling', () {
+    FakeAsync().run((FakeAsync time) {
+      final FakePollingDeviceDiscovery pollingDeviceDiscovery = FakePollingDeviceDiscovery();
+      pollingDeviceDiscovery.startPolling();
+      time.elapse(const Duration(milliseconds: 4001));
 
-        // First check should use the default polling timeout
-        // to quickly populate the list.
-        expect(pollingDeviceDiscovery.lastPollingTimeout, isNull);
+      // First check should use the default polling timeout
+      // to quickly populate the list.
+      expect(pollingDeviceDiscovery.lastPollingTimeout, isNull);
 
-        time.elapse(const Duration(milliseconds: 4001));
+      time.elapse(const Duration(milliseconds: 4001));
 
-        // Subsequent polling should be much longer.
-        expect(pollingDeviceDiscovery.lastPollingTimeout, const Duration(seconds: 30));
-        pollingDeviceDiscovery.stopPolling();
-      });
-    }, overrides: <Type, Generator>{
-      Artifacts: () => Artifacts.test(),
-      Cache: () => cache,
+      // Subsequent polling should be much longer.
+      expect(pollingDeviceDiscovery.lastPollingTimeout, const Duration(seconds: 30));
+      pollingDeviceDiscovery.stopPolling();
     });
   });
 
   group('Filter devices', () {
-    FakeDevice ephemeralOne;
-    FakeDevice ephemeralTwo;
-    FakeDevice nonEphemeralOne;
-    FakeDevice nonEphemeralTwo;
-    FakeDevice unsupported;
-    FakeDevice webDevice;
-    FakeDevice fuchsiaDevice;
-    MockStdio mockStdio;
+    final FakeDevice ephemeralOne = FakeDevice('ephemeralOne', 'ephemeralOne', true);
+    final FakeDevice ephemeralTwo = FakeDevice('ephemeralTwo', 'ephemeralTwo', true);
+    final FakeDevice nonEphemeralOne = FakeDevice('nonEphemeralOne', 'nonEphemeralOne', false);
+    final FakeDevice nonEphemeralTwo = FakeDevice('nonEphemeralTwo', 'nonEphemeralTwo', false);
+    final FakeDevice unsupported = FakeDevice('unsupported', 'unsupported', true, false);
+    final FakeDevice webDevice = FakeDevice('webby', 'webby')
+      ..targetPlatform = Future<TargetPlatform>.value(TargetPlatform.web_javascript);
+    final FakeDevice fuchsiaDevice = FakeDevice('fuchsiay', 'fuchsiay')
+      ..targetPlatform = Future<TargetPlatform>.value(TargetPlatform.fuchsia_x64);
 
-    setUp(() {
-      ephemeralOne = FakeDevice('ephemeralOne', 'ephemeralOne', true);
-      ephemeralTwo = FakeDevice('ephemeralTwo', 'ephemeralTwo', true);
-      nonEphemeralOne = FakeDevice('nonEphemeralOne', 'nonEphemeralOne', false);
-      nonEphemeralTwo = FakeDevice('nonEphemeralTwo', 'nonEphemeralTwo', false);
-      unsupported = FakeDevice('unsupported', 'unsupported', true, false);
-      webDevice = FakeDevice('webby', 'webby')
-        ..targetPlatform = Future<TargetPlatform>.value(TargetPlatform.web_javascript);
-      fuchsiaDevice = FakeDevice('fuchsiay', 'fuchsiay')
-        ..targetPlatform = Future<TargetPlatform>.value(TargetPlatform.fuchsia_x64);
-      mockStdio = MockStdio();
-    });
-
-    testUsingContext('chooses ephemeral device', () async {
+    testWithoutContext('chooses ephemeral device', () async {
       final List<Device> devices = <Device>[
         ephemeralOne,
         nonEphemeralOne,
@@ -190,117 +166,121 @@
         unsupported,
       ];
 
-      final DeviceManager deviceManager = TestDeviceManager(devices);
-      final List<Device> filtered = await deviceManager.findTargetDevices(FlutterProject.current());
+      final DeviceManager deviceManager = TestDeviceManager(
+        devices,
+        logger: BufferLogger.test(),
+        terminal: Terminal.test(),
+      );
+      final List<Device> filtered = await deviceManager.findTargetDevices(FakeFlutterProject());
 
       expect(filtered.single, ephemeralOne);
-    }, overrides: <Type, Generator>{
-      Artifacts: () => Artifacts.test(),
-      Cache: () => cache,
     });
 
-    testUsingContext('choose first non-ephemeral device', () async {
+    testWithoutContext('choose first non-ephemeral device', () async {
       final List<Device> devices = <Device>[
         nonEphemeralOne,
         nonEphemeralTwo,
       ];
+      final MockTerminal mockTerminal = MockTerminal();
+      when(mockTerminal.stdinHasTerminal).thenReturn(true);
+      when(mockTerminal.promptForCharInput(<String>['0', '1', 'q', 'Q'],
+        displayAcceptedCharacters: false,
+        logger: anyNamed('logger'),
+        prompt: anyNamed('prompt'),
+      )).thenAnswer((Invocation invocation) async => '0');
 
-      when(mockStdio.stdinHasTerminal).thenReturn(true);
-      when(globals.terminal.promptForCharInput(<String>['0', '1', 'q', 'Q'],
-      displayAcceptedCharacters: false,
-      logger: globals.logger,
-      prompt: globals.userMessages.flutterChooseOne)
-      ).thenAnswer((Invocation invocation) async => '0');
-
-      final DeviceManager deviceManager = TestDeviceManager(devices);
-      final List<Device> filtered = await deviceManager.findTargetDevices(FlutterProject.current());
+      final DeviceManager deviceManager = TestDeviceManager(
+        devices,
+        logger: BufferLogger.test(),
+        terminal: mockTerminal,
+      );
+      final List<Device> filtered = await deviceManager.findTargetDevices(FakeFlutterProject());
 
       expect(filtered, <Device>[
         nonEphemeralOne
       ]);
-    }, overrides: <Type, Generator>{
-      Artifacts: () => Artifacts.test(),
-      Stdio: () => mockStdio,
-      AnsiTerminal: () => MockTerminal(),
     });
 
-    testUsingContext('choose second non-ephemeral device', () async {
+    testWithoutContext('choose second non-ephemeral device', () async {
       final List<Device> devices = <Device>[
         nonEphemeralOne,
         nonEphemeralTwo,
       ];
+      final MockTerminal mockTerminal = MockTerminal();
 
-      when(mockStdio.stdinHasTerminal).thenReturn(true);
-      when(globals.terminal.promptForCharInput(<String>['0', '1', 'q', 'Q'],
-          displayAcceptedCharacters: false,
-          logger: globals.logger,
-      prompt: globals.userMessages.flutterChooseOne)
-      ).thenAnswer((Invocation invocation) async => '1');
+      when(mockTerminal.stdinHasTerminal).thenReturn(true);
+      when(mockTerminal.promptForCharInput(<String>['0', '1', 'q', 'Q'],
+        displayAcceptedCharacters: false,
+        logger: anyNamed('logger'),
+        prompt: anyNamed('prompt'),
+      )).thenAnswer((Invocation invocation) async => '1');
 
-      final DeviceManager deviceManager = TestDeviceManager(devices);
-      final List<Device> filtered = await deviceManager.findTargetDevices(FlutterProject.current());
+      final DeviceManager deviceManager = TestDeviceManager(
+        devices,
+        logger: BufferLogger.test(),
+        terminal: mockTerminal,
+      );
+      final List<Device> filtered = await deviceManager.findTargetDevices(FakeFlutterProject());
 
       expect(filtered, <Device>[
         nonEphemeralTwo
       ]);
-    }, overrides: <Type, Generator>{
-      Artifacts: () => Artifacts.test(),
-      Stdio: () => mockStdio,
-      AnsiTerminal: () => MockTerminal(),
     });
 
-    testUsingContext('choose first ephemeral device', () async {
+    testWithoutContext('choose first ephemeral device', () async {
       final List<Device> devices = <Device>[
         ephemeralOne,
         ephemeralTwo,
       ];
 
-      when(mockStdio.stdinHasTerminal).thenReturn(true);
-      when(globals.terminal.promptForCharInput(<String>['0', '1', 'q', 'Q'],
-          displayAcceptedCharacters: false,
-          logger: globals.logger,
-        prompt: globals.userMessages.flutterChooseOne)
-      ).thenAnswer((Invocation invocation) async => '0');
+      final MockTerminal mockTerminal = MockTerminal();
 
-      final DeviceManager deviceManager = TestDeviceManager(devices);
-      final List<Device> filtered = await deviceManager.findTargetDevices(FlutterProject.current());
+      when(mockTerminal.stdinHasTerminal).thenReturn(true);
+      when(mockTerminal.promptForCharInput(<String>['0', '1', 'q', 'Q'],
+        displayAcceptedCharacters: false,
+        logger: anyNamed('logger'),
+        prompt: anyNamed('prompt'),
+      )).thenAnswer((Invocation invocation) async => '0');
+
+      final DeviceManager deviceManager = TestDeviceManager(
+        devices,
+        logger: BufferLogger.test(),
+        terminal: mockTerminal,
+      );
+      final List<Device> filtered = await deviceManager.findTargetDevices(FakeFlutterProject());
 
       expect(filtered, <Device>[
         ephemeralOne
       ]);
-    }, overrides: <Type, Generator>{
-      Artifacts: () => Artifacts.test(),
-      Stdio: () => mockStdio,
-      AnsiTerminal: () => MockTerminal(),
     });
 
-    testUsingContext('choose second ephemeral device', () async {
+    testWithoutContext('choose second ephemeral device', () async {
       final List<Device> devices = <Device>[
         ephemeralOne,
         ephemeralTwo,
       ];
+      final MockTerminal mockTerminal = MockTerminal();
 
-      when(mockStdio.stdinHasTerminal).thenReturn(true);
-      when(globals.terminal.promptForCharInput(<String>['0', '1', 'q', 'Q'],
-          displayAcceptedCharacters: false,
-          logger: globals.logger,
-        prompt: globals.userMessages.flutterChooseOne)
-      ).thenAnswer((Invocation invocation) async => '1');
+      when(mockTerminal.stdinHasTerminal).thenReturn(true);
+      when(mockTerminal.promptForCharInput(<String>['0', '1', 'q', 'Q'],
+        displayAcceptedCharacters: false,
+        logger: anyNamed('logger'),
+        prompt: anyNamed('prompt'),
+      )).thenAnswer((Invocation invocation) async => '1');
 
-      final DeviceManager deviceManager = TestDeviceManager(devices);
-      final List<Device> filtered = await deviceManager.findTargetDevices(FlutterProject.current());
+      final DeviceManager deviceManager = TestDeviceManager(
+        devices,
+        logger: BufferLogger.test(),
+        terminal: mockTerminal,
+      );
+      final List<Device> filtered = await deviceManager.findTargetDevices(FakeFlutterProject());
 
       expect(filtered, <Device>[
         ephemeralTwo
       ]);
-    }, overrides: <Type, Generator>{
-      Stdio: () => mockStdio,
-      AnsiTerminal: () => MockTerminal(),
-      Artifacts: () => Artifacts.test(),
-      Cache: () => cache,
     });
 
-    testUsingContext('choose non-ephemeral device', () async {
+    testWithoutContext('choose non-ephemeral device', () async {
       final List<Device> devices = <Device>[
         ephemeralOne,
         ephemeralTwo,
@@ -308,135 +288,141 @@
         nonEphemeralTwo,
       ];
 
-      when(mockStdio.stdinHasTerminal).thenReturn(true);
-      when(globals.terminal.promptForCharInput(<String>['0', '1', '2', '3', 'q', 'Q'],
-        displayAcceptedCharacters: false,
-        logger: globals.logger,
-        prompt: globals.userMessages.flutterChooseOne)
-      ).thenAnswer((Invocation invocation) async => '2');
+      final MockTerminal mockTerminal = MockTerminal();
 
-      final DeviceManager deviceManager = TestDeviceManager(devices);
-      final List<Device> filtered = await deviceManager.findTargetDevices(FlutterProject.current());
+      when(mockTerminal.stdinHasTerminal).thenReturn(true);
+      when(mockTerminal.promptForCharInput(<String>['0', '1', '2', '3', 'q', 'Q'],
+        displayAcceptedCharacters: false,
+        logger: anyNamed('logger'),
+        prompt: anyNamed('prompt'),
+      )).thenAnswer((Invocation invocation) async => '2');
+
+      final DeviceManager deviceManager = TestDeviceManager(
+        devices,
+        logger: BufferLogger.test(),
+        terminal: mockTerminal,
+      );
+
+      final List<Device> filtered = await deviceManager.findTargetDevices(FakeFlutterProject());
 
       expect(filtered, <Device>[
         nonEphemeralOne
       ]);
-    }, overrides: <Type, Generator>{
-      Stdio: () => mockStdio,
-      AnsiTerminal: () => MockTerminal(),
-      Artifacts: () => Artifacts.test(),
-      Cache: () => cache,
     });
 
-    testUsingContext('exit from choose one of available devices', () async {
+    testWithoutContext('exit from choose one of available devices', () async {
       final List<Device> devices = <Device>[
         ephemeralOne,
         ephemeralTwo,
       ];
 
-      when(mockStdio.stdinHasTerminal).thenReturn(true);
-      when(globals.terminal.promptForCharInput(<String>['0', '1', 'q', 'Q'],
-          displayAcceptedCharacters: false,
-          logger: globals.logger,
-          prompt: globals.userMessages.flutterChooseOne)
-      ).thenAnswer((Invocation invocation) async => 'q');
+      final MockTerminal mockTerminal = MockTerminal();
 
-      try {
-        final DeviceManager deviceManager = TestDeviceManager(devices);
-        await deviceManager.findTargetDevices(FlutterProject.current());
-      } on ToolExit catch (e) {
-        expect(e.exitCode, null);
-        expect(e.message, '');
-      }
-    }, overrides: <Type, Generator>{
-      Stdio: () => mockStdio,
-      AnsiTerminal: () => MockTerminal(),
-      Artifacts: () => Artifacts.test(),
-      Cache: () => cache,
+      when(mockTerminal.stdinHasTerminal).thenReturn(true);
+      when(mockTerminal.promptForCharInput(<String>['0', '1', 'q', 'Q'],
+        displayAcceptedCharacters: false,
+        logger: anyNamed('logger'),
+        prompt: anyNamed('prompt'),
+      )).thenAnswer((Invocation invocation) async => 'q');
+
+      final DeviceManager deviceManager = TestDeviceManager(
+        devices,
+        logger: BufferLogger.test(),
+        terminal: mockTerminal,
+      );
+      await expectLater(
+        () async => await deviceManager.findTargetDevices(FakeFlutterProject()),
+        throwsA(isA<ToolExit>())
+      );
     });
 
-    testUsingContext('Removes a single unsupported device', () async {
+    testWithoutContext('Removes a single unsupported device', () async {
       final List<Device> devices = <Device>[
         unsupported,
       ];
 
-      final DeviceManager deviceManager = TestDeviceManager(devices);
-      final List<Device> filtered = await deviceManager.findTargetDevices(FlutterProject.current());
+      final DeviceManager deviceManager = TestDeviceManager(
+        devices,
+        logger: BufferLogger.test(),
+        terminal: Terminal.test(),
+      );
+      final List<Device> filtered = await deviceManager.findTargetDevices(FakeFlutterProject());
 
       expect(filtered, <Device>[]);
-    }, overrides: <Type, Generator>{
-      Artifacts: () => Artifacts.test(),
-      Cache: () => cache,
     });
 
-    testUsingContext('Does not remove an unsupported device if FlutterProject is null', () async {
+    testWithoutContext('Does not remove an unsupported device if FlutterProject is null', () async {
       final List<Device> devices = <Device>[
         unsupported,
       ];
 
-      final DeviceManager deviceManager = TestDeviceManager(devices);
+      final DeviceManager deviceManager = TestDeviceManager(
+        devices,
+        logger: BufferLogger.test(),
+        terminal: Terminal.test(),
+      );
       final List<Device> filtered = await deviceManager.findTargetDevices(null);
 
       expect(filtered, <Device>[unsupported]);
-    }, overrides: <Type, Generator>{
-      Artifacts: () => Artifacts.test(),
-      Cache: () => cache,
     });
 
-    testUsingContext('Removes web and fuchsia from --all', () async {
+    testWithoutContext('Removes web and fuchsia from --all', () async {
       final List<Device> devices = <Device>[
         webDevice,
         fuchsiaDevice,
       ];
-      final DeviceManager deviceManager = TestDeviceManager(devices);
+      final DeviceManager deviceManager = TestDeviceManager(
+        devices,
+        logger: BufferLogger.test(),
+        terminal: Terminal.test(),
+      );
       deviceManager.specifiedDeviceId = 'all';
 
-      final List<Device> filtered = await deviceManager.findTargetDevices(FlutterProject.current());
+      final List<Device> filtered = await deviceManager.findTargetDevices(FakeFlutterProject());
 
       expect(filtered, <Device>[]);
-    }, overrides: <Type, Generator>{
-      Artifacts: () => Artifacts.test(),
-      Cache: () => cache,
     });
 
-    testUsingContext('Removes unsupported devices from --all', () async {
+    testWithoutContext('Removes unsupported devices from --all', () async {
       final List<Device> devices = <Device>[
         nonEphemeralOne,
         nonEphemeralTwo,
         unsupported,
       ];
-      final DeviceManager deviceManager = TestDeviceManager(devices);
+      final DeviceManager deviceManager = TestDeviceManager(
+        devices,
+        logger: BufferLogger.test(),
+        terminal: Terminal.test(),
+      );
       deviceManager.specifiedDeviceId = 'all';
 
-      final List<Device> filtered = await deviceManager.findTargetDevices(FlutterProject.current());
+      final List<Device> filtered = await deviceManager.findTargetDevices(FakeFlutterProject());
 
       expect(filtered, <Device>[
         nonEphemeralOne,
         nonEphemeralTwo,
       ]);
-    }, overrides: <Type, Generator>{
-      Artifacts: () => Artifacts.test(),
-      Cache: () => cache,
     });
 
-    testUsingContext('uses DeviceManager.isDeviceSupportedForProject instead of device.isSupportedForProject', () async {
+    testWithoutContext('uses DeviceManager.isDeviceSupportedForProject instead of device.isSupportedForProject', () async {
       final List<Device> devices = <Device>[
         unsupported,
       ];
-      final TestDeviceManager deviceManager = TestDeviceManager(devices);
+      final TestDeviceManager deviceManager = TestDeviceManager(
+        devices,
+        logger: BufferLogger.test(),
+        terminal: Terminal.test(),
+      );
       deviceManager.isAlwaysSupportedOverride = true;
 
-      final List<Device> filtered = await deviceManager.findTargetDevices(FlutterProject.current());
+      final List<Device> filtered = await deviceManager.findTargetDevices(FakeFlutterProject());
 
       expect(filtered, <Device>[
         unsupported,
       ]);
-    }, overrides: <Type, Generator>{
-      Artifacts: () => Artifacts.test(),
-      Cache: () => cache,
     });
 
-    testUsingContext('does not refresh device cache without a timeout', () async {
+    testWithoutContext('does not refresh device cache without a timeout', () async {
       final List<Device> devices = <Device>[
         ephemeralOne,
       ];
@@ -444,20 +430,22 @@
       when(mockDeviceDiscovery.supportsPlatform).thenReturn(true);
       when(mockDeviceDiscovery.devices).thenAnswer((_) async => devices);
 
-      final DeviceManager deviceManager = TestDeviceManager(<Device>[], deviceDiscoveryOverrides: <DeviceDiscovery>[
-        mockDeviceDiscovery
-      ]);
+      final DeviceManager deviceManager = TestDeviceManager(
+        <Device>[],
+        deviceDiscoveryOverrides: <DeviceDiscovery>[
+          mockDeviceDiscovery
+        ],
+        logger: BufferLogger.test(),
+        terminal: Terminal.test(),
+      );
       deviceManager.specifiedDeviceId = ephemeralOne.id;
       final List<Device> filtered = await deviceManager.findTargetDevices(
-        FlutterProject.current(),
+        FakeFlutterProject(),
       );
 
       expect(filtered.single, ephemeralOne);
       verify(mockDeviceDiscovery.devices).called(1);
       verifyNever(mockDeviceDiscovery.discoverDevices(timeout: anyNamed('timeout')));
-    }, overrides: <Type, Generator>{
-      Artifacts: () => Artifacts.test(),
-      Cache: () => cache,
     });
 
     testUsingContext('refreshes device cache with a timeout', () async {
@@ -470,21 +458,23 @@
       when(mockDeviceDiscovery.discoverDevices(timeout: timeout)).thenAnswer((_) async => devices);
       when(mockDeviceDiscovery.devices).thenAnswer((_) async => devices);
 
-      final DeviceManager deviceManager = TestDeviceManager(<Device>[], deviceDiscoveryOverrides: <DeviceDiscovery>[
-        mockDeviceDiscovery
-      ]);
+      final DeviceManager deviceManager = TestDeviceManager(
+        <Device>[],
+        deviceDiscoveryOverrides: <DeviceDiscovery>[
+          mockDeviceDiscovery
+        ],
+        logger: BufferLogger.test(),
+        terminal: Terminal.test(),
+      );
       deviceManager.specifiedDeviceId = ephemeralOne.id;
       final List<Device> filtered = await deviceManager.findTargetDevices(
-        FlutterProject.current(),
+        FakeFlutterProject(),
         timeout: timeout,
       );
 
       expect(filtered.single, ephemeralOne);
       verify(mockDeviceDiscovery.devices).called(1);
       verify(mockDeviceDiscovery.discoverDevices(timeout: anyNamed('timeout'))).called(1);
-    }, overrides: <Type, Generator>{
-      Artifacts: () => Artifacts.test(),
-      Cache: () => cache,
     });
   });
 
@@ -528,7 +518,9 @@
 class TestDeviceManager extends DeviceManager {
     TestDeviceManager(List<Device> allDevices, {
     List<DeviceDiscovery> deviceDiscoveryOverrides,
-  }) {
+    @required Logger logger,
+    @required Terminal terminal,
+  }) : super(logger: logger, terminal: terminal, userMessages: UserMessages()) {
     _fakeDeviceDiscoverer = FakePollingDeviceDiscovery();
     _deviceDiscoverers = <DeviceDiscovery>[
       _fakeDeviceDiscoverer,
@@ -557,7 +549,6 @@
   }
 }
 
-class MockProcess extends Mock implements Process {}
 class MockTerminal extends Mock implements AnsiTerminal {}
-class MockStdio extends Mock implements Stdio {}
 class MockDeviceDiscovery extends Mock implements DeviceDiscovery {}
+class FakeFlutterProject extends Fake implements FlutterProject {}