revert #48985 (#49572)

diff --git a/packages/flutter_tools/lib/src/android/android_emulator.dart b/packages/flutter_tools/lib/src/android/android_emulator.dart
index b7c0557..0aeb57d 100644
--- a/packages/flutter_tools/lib/src/android/android_emulator.dart
+++ b/packages/flutter_tools/lib/src/android/android_emulator.dart
@@ -8,8 +8,12 @@
 
 import '../android/android_sdk.dart';
 import '../android/android_workflow.dart';
+import '../base/common.dart';
 import '../base/file_system.dart';
+import '../base/io.dart';
 import '../base/process.dart';
+import '../base/utils.dart';
+import '../convert.dart';
 import '../device.dart';
 import '../emulator.dart';
 import '../globals.dart' as globals;
@@ -50,18 +54,59 @@
 
   @override
   Future<void> launch() async {
-    final Future<void> launchResult = processUtils.run(
-      <String>[getEmulatorPath(), '-avd', id],
-      throwOnError: true,
+    final Process process = await processUtils.start(
+      <String>[getEmulatorPath(androidSdk), '-avd', id],
     );
-    // The emulator continues running on a successful launch, so if it hasn't
-    // quit within 3 seconds we assume that's a success and just return. This
-    // means that on a slow machine, a failure that takes more than three
-    // seconds won't be recognized as such... :-/
-    return Future.any<void>(<Future<void>>[
-      launchResult,
-      Future<void>.delayed(const Duration(seconds: 3)),
+
+    // Record output from the emulator process.
+    final List<String> stdoutList = <String>[];
+    final List<String> stderrList = <String>[];
+    final StreamSubscription<String> stdoutSubscription = process.stdout
+      .transform<String>(utf8.decoder)
+      .transform<String>(const LineSplitter())
+      .listen(stdoutList.add);
+    final StreamSubscription<String> stderrSubscription = process.stderr
+      .transform<String>(utf8.decoder)
+      .transform<String>(const LineSplitter())
+      .listen(stderrList.add);
+    final Future<void> stdioFuture = waitGroup<void>(<Future<void>>[
+      stdoutSubscription.asFuture<void>(),
+      stderrSubscription.asFuture<void>(),
     ]);
+
+    // The emulator continues running on success, so we don't wait for the
+    // process to complete before continuing. However, if the process fails
+    // after the startup phase (3 seconds), then we only echo its output if
+    // its error code is non-zero and its stderr is non-empty.
+    bool earlyFailure = true;
+    unawaited(process.exitCode.then((int status) async {
+      if (status == 0) {
+        globals.printTrace('The Android emulator exited successfully');
+        return;
+      }
+      // Make sure the process' stdout and stderr are drained.
+      await stdioFuture;
+      unawaited(stdoutSubscription.cancel());
+      unawaited(stderrSubscription.cancel());
+      if (stdoutList.isNotEmpty) {
+        globals.printTrace('Android emulator stdout:');
+        stdoutList.forEach(globals.printTrace);
+      }
+      if (!earlyFailure && stderrList.isEmpty) {
+        globals.printStatus('The Android emulator exited with code $status');
+        return;
+      }
+      final String when = earlyFailure ? 'during startup' : 'after startup';
+      globals.printError('The Android emulator exited with code $status $when');
+      globals.printError('Android emulator stderr:');
+      stderrList.forEach(globals.printError);
+      globals.printError('Address these issues and try again.');
+    }));
+
+    // Wait a few seconds for the emulator to start.
+    await Future<void>.delayed(const Duration(seconds: 3));
+    earlyFailure = false;
+    return;
   }
 }
 
diff --git a/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart b/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart
index 3f159aa..a7dda4c 100644
--- a/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart
+++ b/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart
@@ -22,11 +22,14 @@
 import '../base/terminal.dart';
 import '../base/utils.dart';
 import '../build_info.dart';
+import '../compile.dart';
 import '../convert.dart';
 import '../devfs.dart';
 import '../device.dart';
 import '../features.dart';
 import '../globals.dart' as globals;
+import '../platform_plugins.dart';
+import '../plugins.dart';
 import '../project.dart';
 import '../reporting/reporting.dart';
 import '../resident_runner.dart';
@@ -98,6 +101,10 @@
   final List<String> dartDefines;
   DateTime firstBuildTime;
 
+  // Used with the new compiler to generate a bootstrap file containing plugins
+  // and platform initialization.
+  Directory _generatedEntrypointDirectory;
+
   // Only the debug builds of the web support the service protocol.
   @override
   bool get supportsServiceProtocol => isRunningDebug && deviceIsDebuggable;
@@ -151,6 +158,7 @@
     await _stdOutSub?.cancel();
     await _webFs?.stop();
     await device.device.stopApp(null);
+    _generatedEntrypointDirectory?.deleteSync(recursive: true);
     if (ChromeLauncher.hasChromeInstance) {
       final Chrome chrome = await ChromeLauncher.connectedInstance;
       await chrome.close();
@@ -478,6 +486,46 @@
     return OperationResult.ok;
   }
 
+  // Flutter web projects need to include a generated main entrypoint to call the
+  // appropriate bootstrap method and inject plugins.
+  // Keep this in sync with build_system/targets/web.dart.
+  Future<String> _generateEntrypoint(String main, String packagesPath) async {
+    File result = _generatedEntrypointDirectory?.childFile('web_entrypoint.dart');
+    if (_generatedEntrypointDirectory == null) {
+      _generatedEntrypointDirectory ??= globals.fs.systemTempDirectory.createTempSync('flutter_tools.')
+        ..createSync();
+      result = _generatedEntrypointDirectory.childFile('web_entrypoint.dart');
+
+      final bool hasWebPlugins = findPlugins(flutterProject)
+        .any((Plugin p) => p.platforms.containsKey(WebPlugin.kConfigKey));
+      await injectPlugins(flutterProject, checkProjects: true);
+
+      final PackageUriMapper packageUriMapper = PackageUriMapper(main, packagesPath, null, null);
+      final String generatedPath = globals.fs.currentDirectory
+        .childDirectory('lib')
+        .childFile('generated_plugin_registrant.dart')
+        .absolute.path;
+      final Uri generatedImport = packageUriMapper.map(generatedPath);
+
+      final String entrypoint = <String>[
+        'import "${packageUriMapper.map(main)}" as entrypoint;',
+        'import "dart:ui" as ui;',
+        if (hasWebPlugins)
+          'import "package:flutter_web_plugins/flutter_web_plugins.dart";',
+        if (hasWebPlugins)
+          'import "$generatedImport";',
+        'Future<void> main() async {',
+        if (hasWebPlugins)
+          '  registerPlugins(webPluginRegistry);'
+        '  await ui.webOnlyInitializePlatform();',
+        '  entrypoint.main();',
+        '}',
+      ].join('\n');
+      result.writeAsStringSync(entrypoint);
+    }
+    return result.path;
+  }
+
   Future<UpdateFSReport> _updateDevFS({bool fullRestart = false}) async {
     final bool isFirstUpload = !assetBundle.wasBuiltOnce();
     final bool rebuildBundle = assetBundle.needsBuild();
@@ -499,7 +547,7 @@
       timeout: timeoutConfiguration.fastOperation,
     );
     final UpdateFSReport report = await device.devFS.update(
-      mainPath: mainPath,
+      mainPath: await _generateEntrypoint(mainPath, packagesFilePath),
       target: target,
       bundle: assetBundle,
       firstBuildTime: firstBuildTime,
diff --git a/packages/flutter_tools/lib/src/build_system/targets/web.dart b/packages/flutter_tools/lib/src/build_system/targets/web.dart
index 12ac2e1..a8d0470 100644
--- a/packages/flutter_tools/lib/src/build_system/targets/web.dart
+++ b/packages/flutter_tools/lib/src/build_system/targets/web.dart
@@ -32,6 +32,7 @@
 const String kCspMode = 'cspMode';
 
 /// Generates an entry point for a web target.
+// Keep this in sync with build_runner/resident_web_runner.dart
 class WebEntrypointTarget extends Target {
   const WebEntrypointTarget();
 
diff --git a/packages/flutter_tools/lib/src/commands/emulators.dart b/packages/flutter_tools/lib/src/commands/emulators.dart
index 14671f3..0eaab4c 100644
--- a/packages/flutter_tools/lib/src/commands/emulators.dart
+++ b/packages/flutter_tools/lib/src/commands/emulators.dart
@@ -69,16 +69,7 @@
         "More than one emulator matches '$id':",
       );
     } else {
-      try {
-        await emulators.first.launch();
-      }
-      catch (e) {
-        if (e is String) {
-          globals.printError(e);
-        } else {
-          rethrow;
-        }
-      }
+      await emulators.first.launch();
     }
   }
 
diff --git a/packages/flutter_tools/lib/src/web/bootstrap.dart b/packages/flutter_tools/lib/src/web/bootstrap.dart
index d0435a7..92f2b2c 100644
--- a/packages/flutter_tools/lib/src/web/bootstrap.dart
+++ b/packages/flutter_tools/lib/src/web/bootstrap.dart
@@ -55,7 +55,8 @@
         // once we've reloaded every module, trigger the hot reload.
         if (reloadCount == modules.length) {
           require(["$entrypoint", "dart_sdk"], function(app, dart_sdk) {
-            window.\$mainEntrypoint = app.main.main;
+            // See L81 below for an explanation.
+            window.\$mainEntrypoint = app[Object.keys(app)[0]].main;
             window.\$hotReload(resolve);
           });
         }
@@ -78,22 +79,23 @@
   let voidToNull = () => (voidToNull = dart_sdk.dart.constFn(dart_sdk.dart.fnType(dart_sdk.core.Null, [dart_sdk.dart.void])))();
 
   // Attach the main entrypoint and hot reload functionality to the window.
-  window.\$mainEntrypoint = app.main.main;
+  // The app module will have a single property which contains the actual application
+  // code. The property name is based off of the entrypoint that is generated, for example
+  // the file `foo/bar/baz.dart` will generate a property named approximately
+  // `foo__bar__baz`. Rather than attempt to guess, we assume the first property of
+  // this object is the module.
+  window.\$mainEntrypoint = app[Object.keys(app)[0]].main;
   if (window.\$hotReload == null) {
     window.\$hotReload = function(cb) {
       dart_sdk.developer.invokeExtension("ext.flutter.disassemble", "{}").then((_) => {
         dart_sdk.dart.hotRestart();
-        dart_sdk.ui.webOnlyInitializePlatform().then(dart_sdk.core.Null, dart_sdk.dart.fn(_ => {
-          window.\$mainEntrypoint();
-          window.requestAnimationFrame(cb);
-        }, voidToNull()));
+        window.\$mainEntrypoint();
+        window.requestAnimationFrame(cb);
       });
     }
   }
 
-  dart_sdk.ui.webOnlyInitializePlatform().then(dart_sdk.core.Null, dart_sdk.dart.fn(_ => {
-    app.main.main();
-  }, voidToNull()));
+  window.\$mainEntrypoint();
 });
 
 // Require JS configuration.
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/assemble_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/assemble_test.dart
index 3eeef20..ceeedc1 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/assemble_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/assemble_test.dart
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 import 'package:args/command_runner.dart';
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
 import 'package:flutter_tools/src/build_system/build_system.dart';
 import 'package:flutter_tools/src/cache.dart';
@@ -53,7 +52,7 @@
     final CommandRunner<void> commandRunner = createTestCommandRunner(AssembleCommand());
 
     expect(commandRunner.run(<String>['assemble', 'debug_macos_bundle_flutter_assets']),
-      throwsA(isInstanceOf<ToolExit>()));
+      throwsToolExit());
   });
 
   testbed.test('Throws ToolExit if called with non-existent rule', () async {
@@ -64,7 +63,7 @@
     final CommandRunner<void> commandRunner = createTestCommandRunner(AssembleCommand());
 
     expect(commandRunner.run(<String>['assemble', '-o Output', 'undefined']),
-      throwsA(isInstanceOf<ToolExit>()));
+      throwsToolExit());
   });
 
   testbed.test('Does not log stack traces during build failure', () async {
@@ -78,7 +77,7 @@
     final CommandRunner<void> commandRunner = createTestCommandRunner(AssembleCommand());
 
     await expectLater(commandRunner.run(<String>['assemble', '-o Output', 'debug_macos_bundle_flutter_assets']),
-      throwsA(isInstanceOf<ToolExit>()));
+      throwsToolExit());
     expect(testLogger.errorText, contains('bar'));
     expect(testLogger.errorText, isNot(contains(testStackTrace.toString())));
   });
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart
index c51c372..2231ed7 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart
@@ -240,7 +240,7 @@
         });
         testDeviceManager.addDevice(device);
         expect(createTestCommandRunner(AttachCommand()).run(<String>['attach']),
-               throwsA(isA<ToolExit>()));
+               throwsToolExit());
       }, overrides: <Type, Generator>{
         FileSystem: () => testFileSystem,
         ProcessManager: () => FakeProcessManager.any(),
@@ -619,7 +619,7 @@
       final AttachCommand command = AttachCommand();
       await expectLater(
         createTestCommandRunner(command).run(<String>['attach']),
-        throwsA(isInstanceOf<ToolExit>()),
+        throwsToolExit(),
       );
       expect(testLogger.statusText, contains('No supported devices connected'));
     }, overrides: <Type, Generator>{
@@ -642,7 +642,7 @@
       testDeviceManager.addDevice(aDeviceWithId('yy2'));
       await expectLater(
         createTestCommandRunner(command).run(<String>['attach']),
-        throwsA(isInstanceOf<ToolExit>()),
+        throwsToolExit(),
       );
       expect(testLogger.statusText, contains('More than one device'));
       expect(testLogger.statusText, contains('xx1'));
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/build_fuchsia_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/build_fuchsia_test.dart
index 404ab86..3597a17 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/build_fuchsia_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/build_fuchsia_test.dart
@@ -5,7 +5,6 @@
 import 'package:file/memory.dart';
 import 'package:platform/platform.dart';
 
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
 import 'package:flutter_tools/src/build_info.dart';
 import 'package:flutter_tools/src/cache.dart';
@@ -50,7 +49,7 @@
       expect(
           createTestCommandRunner(command)
               .run(const <String>['build', 'fuchsia']),
-          throwsA(isInstanceOf<ToolExit>()));
+          throwsToolExit());
     }, overrides: <Type, Generator>{
       Platform: () => linuxPlatform,
       FileSystem: () => MemoryFileSystem(),
@@ -67,7 +66,7 @@
       expect(
           createTestCommandRunner(command)
               .run(const <String>['build', 'fuchsia']),
-          throwsA(isInstanceOf<ToolExit>()));
+          throwsToolExit());
     }, overrides: <Type, Generator>{
       Platform: () => linuxPlatform,
       FileSystem: () => MemoryFileSystem(),
@@ -89,7 +88,7 @@
       expect(
           createTestCommandRunner(command)
               .run(const <String>['build', 'fuchsia']),
-          throwsA(isInstanceOf<ToolExit>()));
+          throwsToolExit());
     }, overrides: <Type, Generator>{
       Platform: () => windowsPlatform,
       FileSystem: () => MemoryFileSystem(),
@@ -111,7 +110,7 @@
       expect(
           createTestCommandRunner(command)
               .run(const <String>['build', 'fuchsia']),
-          throwsA(isInstanceOf<ToolExit>()));
+          throwsToolExit());
     }, overrides: <Type, Generator>{
       Platform: () => linuxPlatform,
       FileSystem: () => MemoryFileSystem(),
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/build_linux_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/build_linux_test.dart
index e6a7244..9f1f166 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/build_linux_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/build_linux_test.dart
@@ -8,7 +8,6 @@
 import 'package:mockito/mockito.dart';
 import 'package:process/process.dart';
 
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
 import 'package:flutter_tools/src/base/io.dart';
 import 'package:flutter_tools/src/cache.dart';
@@ -101,7 +100,7 @@
 
     expect(createTestCommandRunner(command).run(
       const <String>['build', 'linux']
-    ), throwsA(isInstanceOf<ToolExit>()));
+    ), throwsToolExit());
   }, overrides: <Type, Generator>{
     Platform: () => notLinuxPlatform,
     FileSystem: () => MemoryFileSystem(),
@@ -220,7 +219,7 @@
     final CommandRunner<void> runner = createTestCommandRunner(BuildCommand());
 
     expect(() => runner.run(<String>['build', 'linux']),
-        throwsA(isInstanceOf<ToolExit>()));
+        throwsToolExit());
   }, overrides: <Type, Generator>{
     FeatureFlags: () => TestFeatureFlags(isLinuxEnabled: false),
   });
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/build_macos_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/build_macos_test.dart
index 18ad8d4..2797f144 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/build_macos_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/build_macos_test.dart
@@ -6,7 +6,6 @@
 import 'package:file/memory.dart';
 import 'package:platform/platform.dart';
 
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
 import 'package:flutter_tools/src/base/io.dart';
 import 'package:flutter_tools/src/build_info.dart';
@@ -127,7 +126,7 @@
 
     expect(createTestCommandRunner(command).run(
       const <String>['build', 'macos']
-    ), throwsA(isInstanceOf<ToolExit>()));
+    ), throwsToolExit());
   }, overrides: <Type, Generator>{
     Platform: () => notMacosPlatform,
     FileSystem: () => MemoryFileSystem(),
@@ -206,7 +205,7 @@
     final CommandRunner<void> runner = createTestCommandRunner(BuildCommand());
 
     expect(() => runner.run(<String>['build', 'macos']),
-        throwsA(isInstanceOf<ToolExit>()));
+        throwsToolExit());
   }, overrides: <Type, Generator>{
     FeatureFlags: () => TestFeatureFlags(isMacOSEnabled: false),
   });
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/build_web_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/build_web_test.dart
index 96c790d..b5026e5 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/build_web_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/build_web_test.dart
@@ -5,7 +5,6 @@
 import 'package:args/command_runner.dart';
 import 'package:platform/platform.dart';
 
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/build_info.dart';
 import 'package:flutter_tools/src/build_system/build_system.dart';
 import 'package:flutter_tools/src/cache.dart';
@@ -60,7 +59,7 @@
       false,
       const <String>[],
       false,
-    ), throwsA(isInstanceOf<ToolExit>()));
+    ), throwsToolExit());
   }));
 
   test('Refuses to build using runner when missing index.html', () => testbed.run(() async {
@@ -82,7 +81,7 @@
     final CommandRunner<void> runner = createTestCommandRunner(BuildCommand());
 
     expect(() => runner.run(<String>['build', 'web', '--debug']),
-        throwsA(isInstanceOf<UsageException>()));
+        throwsA(isA<UsageException>()));
   }, overrides: <Type, Generator>{
     FeatureFlags: () => TestFeatureFlags(isWebEnabled: true),
   }));
@@ -91,7 +90,7 @@
     final CommandRunner<void> runner = createTestCommandRunner(BuildCommand());
 
     expect(() => runner.run(<String>['build', 'web']),
-        throwsA(isInstanceOf<ToolExit>()));
+        throwsToolExit());
   }, overrides: <Type, Generator>{
     FeatureFlags: () => TestFeatureFlags(isWebEnabled: false),
   }));
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/build_windows_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/build_windows_test.dart
index 5b2f571..0ec38b5 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/build_windows_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/build_windows_test.dart
@@ -5,7 +5,6 @@
 import 'package:file/memory.dart';
 import 'package:platform/platform.dart';
 
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
 import 'package:flutter_tools/src/base/io.dart';
 import 'package:flutter_tools/src/cache.dart';
@@ -77,7 +76,7 @@
     setUpMockProjectFilesForBuild();
     expect(createTestCommandRunner(command).run(
       const <String>['build', 'windows']
-    ), throwsA(isInstanceOf<ToolExit>()));
+    ), throwsToolExit());
   }, overrides: <Type, Generator>{
     Platform: () => windowsPlatform,
     FileSystem: () => MemoryFileSystem(style: FileSystemStyle.windows),
@@ -110,7 +109,7 @@
 
     expect(createTestCommandRunner(command).run(
       const <String>['build', 'windows']
-    ), throwsA(isInstanceOf<ToolExit>()));
+    ), throwsToolExit());
   }, overrides: <Type, Generator>{
     Platform: () => notWindowsPlatform,
     FileSystem: () => MemoryFileSystem(style: FileSystemStyle.windows),
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/config_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/config_test.dart
index bcb4338..8c6def3 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/config_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/config_test.dart
@@ -7,7 +7,6 @@
 import 'package:args/command_runner.dart';
 import 'package:flutter_tools/src/android/android_sdk.dart';
 import 'package:flutter_tools/src/android/android_studio.dart';
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/base/context.dart';
 import 'package:flutter_tools/src/build_info.dart';
 import 'package:flutter_tools/src/cache.dart';
@@ -102,7 +101,7 @@
       expect(() => commandRunner.run(<String>[
         'config',
         '--build-dir=/foo',
-      ]), throwsA(isInstanceOf<ToolExit>()));
+      ]), throwsToolExit());
       verifyNoAnalytics();
     }, overrides: <Type, Generator>{
       Usage: () => mockUsage,
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/daemon_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/daemon_test.dart
index ba5053b..0cda035 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/daemon_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/daemon_test.dart
@@ -47,7 +47,7 @@
       final Map<String, dynamic> response = await responses.stream.firstWhere(_notEvent);
       expect(response['id'], 0);
       expect(response['result'], isNotEmpty);
-      expect(response['result'] is String, true);
+      expect(response['result'], isA<String>());
       await responses.close();
       await commands.close();
     });
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/run_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/run_test.dart
index ccf8b2f..0257dc1 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/run_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/run_test.dart
@@ -111,7 +111,7 @@
         ]);
         fail('Expect exception');
       } catch (e) {
-        expect(e, isInstanceOf<ToolExit>());
+        expect(e, isA<ToolExit>());
       }
 
       final BufferLogger bufferLogger = globals.logger as BufferLogger;
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/version_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/version_test.dart
index 45a0330..bb11c7a 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/version_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/version_test.dart
@@ -107,7 +107,7 @@
           '--no-pub',
           version,
         ]),
-        throwsA(isInstanceOf<ToolExit>()),
+        throwsToolExit(),
       );
     }, overrides: <Type, Generator>{
       ProcessManager: () => MockProcessManager(),
@@ -119,7 +119,7 @@
         await command.getTags();
         fail('ToolExit expected');
       } catch(e) {
-        expect(e, isInstanceOf<ToolExit>());
+        expect(e, isA<ToolExit>());
       }
     }, overrides: <Type, Generator>{
       ProcessManager: () => MockProcessManager(failGitTag: true),
diff --git a/packages/flutter_tools/test/commands.shard/permeable/build_bundle_test.dart b/packages/flutter_tools/test/commands.shard/permeable/build_bundle_test.dart
index 3018b67..2db9ff8 100644
--- a/packages/flutter_tools/test/commands.shard/permeable/build_bundle_test.dart
+++ b/packages/flutter_tools/test/commands.shard/permeable/build_bundle_test.dart
@@ -4,7 +4,6 @@
 
 import 'package:args/command_runner.dart';
 import 'package:file/memory.dart';
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
 import 'package:flutter_tools/src/build_system/build_system.dart';
 import 'package:flutter_tools/src/build_system/targets/dart.dart';
@@ -109,7 +108,7 @@
       'bundle',
       '--no-pub',
       '--target-platform=windows-x64',
-    ]), throwsA(isInstanceOf<ToolExit>()));
+    ]), throwsToolExit());
   }, overrides: <Type, Generator>{
     FileSystem: () => MemoryFileSystem(),
     ProcessManager: () => FakeProcessManager.any(),
@@ -127,7 +126,7 @@
       'bundle',
       '--no-pub',
       '--target-platform=linux-x64',
-    ]), throwsA(isInstanceOf<ToolExit>()));
+    ]), throwsToolExit());
   }, overrides: <Type, Generator>{
     FileSystem: () => MemoryFileSystem(),
     ProcessManager: () => FakeProcessManager.any(),
@@ -145,7 +144,7 @@
       'bundle',
       '--no-pub',
       '--target-platform=darwin-x64',
-    ]), throwsA(isInstanceOf<ToolExit>()));
+    ]), throwsToolExit());
   }, overrides: <Type, Generator>{
     FileSystem: () => MemoryFileSystem(),
     ProcessManager: () => FakeProcessManager.any(),
diff --git a/packages/flutter_tools/test/commands.shard/permeable/upgrade_test.dart b/packages/flutter_tools/test/commands.shard/permeable/upgrade_test.dart
index 4fc4ebc..e89aac6 100644
--- a/packages/flutter_tools/test/commands.shard/permeable/upgrade_test.dart
+++ b/packages/flutter_tools/test/commands.shard/permeable/upgrade_test.dart
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
 import 'package:flutter_tools/src/base/io.dart';
 
@@ -63,7 +62,7 @@
         const GitTagVersion.unknown(),
         flutterVersion,
       );
-      expect(result, throwsA(isInstanceOf<ToolExit>()));
+      expect(result, throwsToolExit());
     }, overrides: <Type, Generator>{
       Platform: () => fakePlatform,
     });
@@ -89,7 +88,7 @@
         gitTagVersion,
         flutterVersion,
       );
-      expect(result, throwsA(isA<ToolExit>()));
+      expect(result, throwsToolExit());
     }, overrides: <Type, Generator>{
       Platform: () => fakePlatform,
     });
diff --git a/packages/flutter_tools/test/general.shard/android/android_device_test.dart b/packages/flutter_tools/test/general.shard/android/android_device_test.dart
index c6ade4c..62f2171 100644
--- a/packages/flutter_tools/test/general.shard/android/android_device_test.dart
+++ b/packages/flutter_tools/test/general.shard/android/android_device_test.dart
@@ -13,7 +13,6 @@
 import 'package:flutter_tools/src/application_package.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
 import 'package:flutter_tools/src/base/io.dart';
-import 'package:flutter_tools/src/base/process.dart';
 import 'package:flutter_tools/src/build_info.dart';
 import 'package:flutter_tools/src/device.dart';
 import 'package:flutter_tools/src/project.dart';
@@ -44,45 +43,6 @@
   File get file => MockFile();
 }
 
-class MockProcessUtils extends Mock implements ProcessUtils {
-  @override
-  Future<RunResult> run(
-      List<String> cmd, {
-        bool throwOnError = false,
-        RunResultChecker whiteListFailures,
-        String workingDirectory,
-        bool allowReentrantFlutter = false,
-        Map<String, String> environment,
-        Duration timeout,
-        int timeoutRetries = 0,
-      }) async {
-    if (cmd.contains('version')) {
-      return RunResult(ProcessResult(0, 0, 'Android Debug Bridge version 1.0.41', ''), cmd);
-    }
-    if (cmd.contains('android.intent.action.RUN')) {
-      _runCmd = cmd;
-    }
-    return RunResult(ProcessResult(0, 0, '', ''), cmd);
-  }
-
-  @override
-  Future<int> stream(
-      List<String> cmd, {
-        String workingDirectory,
-        bool allowReentrantFlutter = false,
-        String prefix = '',
-        bool trace = false,
-        RegExp filter,
-        StringConverter mapFunction,
-        Map<String, String> environment,
-      }) async {
-    return 0;
-  }
-
-  List<String> _runCmd;
-  List<String> get runCmd => _runCmd;
-}
-
 class MockAndroidSdkVersion extends Mock implements AndroidSdkVersion {}
 
 void main() {
@@ -97,13 +57,11 @@
       MockAndroidApk mockApk;
       MockProcessManager mockProcessManager;
       MockAndroidSdk mockAndroidSdk;
-      MockProcessUtils mockProcessUtils;
 
       setUp(() {
         mockApk = MockAndroidApk();
         mockProcessManager = MockProcessManager();
         mockAndroidSdk = MockAndroidSdk();
-        mockProcessUtils = MockProcessUtils();
       });
 
       testUsingContext('succeeds with --cache-sksl', () async {
@@ -124,6 +82,20 @@
         )).thenAnswer((_) async {
           return ProcessResult(0, 0, '[ro.build.version.sdk]: [24]', '');
         });
+        when(mockProcessManager.run(
+          any,
+          workingDirectory: anyNamed('workingDirectory'),
+          environment: anyNamed('environment')
+        )).thenAnswer((_) async {
+          return ProcessResult(0, 0, '', '');
+        });
+        when(mockProcessManager.start(
+          any,
+          workingDirectory: anyNamed('workingDirectory'),
+          environment: anyNamed('environment')
+        )).thenAnswer((_) async {
+          return FakeProcess();
+        });
 
         final LaunchResult launchResult = await device.startApp(
           mockApk,
@@ -134,18 +106,14 @@
           ),
           platformArgs: <String, dynamic>{},
         );
-        expect(launchResult.started, isTrue);
 
-        final int cmdIndex = mockProcessUtils.runCmd.indexOf('cache-sksl');
-        expect(
-            mockProcessUtils.runCmd.sublist(cmdIndex - 1, cmdIndex + 2),
-            equals(<String>['--ez', 'cache-sksl', 'true']),
-        );
+        expect(launchResult.started, isTrue);
+        expect(verify(mockProcessManager.run(captureAny)).captured.last.join(','),
+          contains(<String>['--ez', 'cache-sksl', 'true'].join(',')));
       }, overrides: <Type, Generator>{
         AndroidSdk: () => mockAndroidSdk,
         FileSystem: () => MemoryFileSystem(),
         ProcessManager: () => mockProcessManager,
-        ProcessUtils: () => mockProcessUtils,
       });
 
       testUsingContext('can run a release build on x64', () async {
@@ -166,6 +134,20 @@
         )).thenAnswer((_) async {
           return ProcessResult(0, 0, '[ro.build.version.sdk]: [24]\n[ro.product.cpu.abi]: [x86_64]', '');
         });
+        when(mockProcessManager.run(
+          any,
+          workingDirectory: anyNamed('workingDirectory'),
+          environment: anyNamed('environment')
+        )).thenAnswer((_) async {
+          return ProcessResult(0, 0, '', '');
+        });
+        when(mockProcessManager.start(
+          any,
+          workingDirectory: anyNamed('workingDirectory'),
+          environment: anyNamed('environment')
+        )).thenAnswer((_) async {
+          return FakeProcess();
+        });
 
         final LaunchResult launchResult = await device.startApp(
           mockApk,
@@ -180,7 +162,6 @@
         AndroidSdk: () => mockAndroidSdk,
         FileSystem: () => MemoryFileSystem(),
         ProcessManager: () => mockProcessManager,
-        ProcessUtils: () => mockProcessUtils,
       });
     });
   });
@@ -652,7 +633,7 @@
       when(mockProcessManager.run(argThat(contains('forward'))))
           .thenAnswer((_) async => ProcessResult(0, 0, '123456', ''));
 
-      expect(forwarder.forward(123, hostPort: 456), throwsA(isInstanceOf<ProcessException>()));
+      expect(forwarder.forward(123, hostPort: 456), throwsA(isA<ProcessException>()));
     }, overrides: <Type, Generator>{
       ProcessManager: () => mockProcessManager,
     });
diff --git a/packages/flutter_tools/test/general.shard/android/android_emulator_test.dart b/packages/flutter_tools/test/general.shard/android/android_emulator_test.dart
index 5f37cc2..9b776a2 100644
--- a/packages/flutter_tools/test/general.shard/android/android_emulator_test.dart
+++ b/packages/flutter_tools/test/general.shard/android/android_emulator_test.dart
@@ -2,11 +2,22 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import 'dart:async';
+
+import 'package:file/file.dart';
+import 'package:file/memory.dart';
+import 'package:flutter_tools/src/android/android_sdk.dart'
+  show getEmulatorPath, AndroidSdk, androidSdk;
 import 'package:flutter_tools/src/android/android_emulator.dart';
+import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/device.dart';
+import 'package:mockito/mockito.dart';
+import 'package:quiver/testing/async.dart';
 
 import '../../src/common.dart';
 import '../../src/context.dart';
+import '../../src/fake_process_manager.dart';
+import '../../src/mocks.dart' show MockAndroidSdk;
 
 void main() {
   group('android_emulator', () {
@@ -18,8 +29,10 @@
     });
     testUsingContext('flags emulators with config', () {
       const String emulatorID = '1234';
-      final AndroidEmulator emulator =
-          AndroidEmulator(emulatorID, <String, String>{'name': 'test'});
+      final AndroidEmulator emulator = AndroidEmulator(
+        emulatorID,
+        <String, String>{'name': 'test'},
+      );
       expect(emulator.id, emulatorID);
       expect(emulator.hasConfig, true);
     });
@@ -31,8 +44,7 @@
         'hw.device.manufacturer': manufacturer,
         'avd.ini.displayname': displayName,
       };
-      final AndroidEmulator emulator =
-          AndroidEmulator(emulatorID, properties);
+      final AndroidEmulator emulator = AndroidEmulator(emulatorID, properties);
       expect(emulator.id, emulatorID);
       expect(emulator.name, displayName);
       expect(emulator.manufacturer, manufacturer);
@@ -45,8 +57,7 @@
       final Map<String, String> properties = <String, String>{
         'avd.ini.displayname': displayName,
       };
-      final AndroidEmulator emulator =
-          AndroidEmulator(emulatorID, properties);
+      final AndroidEmulator emulator = AndroidEmulator(emulatorID, properties);
       expect(emulator.name, displayName);
     });
     testUsingContext('uses cleaned up ID if no displayname is set', () {
@@ -56,8 +67,7 @@
       final Map<String, String> properties = <String, String>{
         'avd.ini.notadisplayname': 'this is not a display name',
       };
-      final AndroidEmulator emulator =
-          AndroidEmulator(emulatorID, properties);
+      final AndroidEmulator emulator = AndroidEmulator(emulatorID, properties);
       expect(emulator.name, 'This is my ID');
     });
     testUsingContext('parses ini files', () {
@@ -74,4 +84,98 @@
       expect(results['avd.ini.displayname'], 'dispName');
     });
   });
+
+  group('Android emulator launch ', () {
+    const String emulatorID = 'i1234';
+    const String errorText = '[Android emulator test error]';
+    MockAndroidSdk mockSdk;
+    FakeProcessManager successProcessManager;
+    FakeProcessManager errorProcessManager;
+    FakeProcessManager lateFailureProcessManager;
+    MemoryFileSystem fs;
+
+    setUp(() {
+      fs = MemoryFileSystem();
+      mockSdk = MockAndroidSdk();
+      when(mockSdk.emulatorPath).thenReturn('emulator');
+
+      const List<String> command = <String>[
+        'emulator', '-avd', emulatorID,
+      ];
+
+      successProcessManager = FakeProcessManager.list(<FakeCommand>[
+        const FakeCommand(command: command),
+      ]);
+
+      errorProcessManager = FakeProcessManager.list(<FakeCommand>[
+        const FakeCommand(
+          command: command,
+          exitCode: 1,
+          stderr: errorText,
+          stdout: 'dummy text',
+          duration: Duration(seconds: 1),
+        ),
+      ]);
+
+      lateFailureProcessManager = FakeProcessManager.list(<FakeCommand>[
+        const FakeCommand(
+          command: command,
+          exitCode: 1,
+          stderr: '',
+          stdout: 'dummy text',
+          duration: Duration(seconds: 4),
+        ),
+      ]);
+    });
+
+    testUsingContext('succeeds', () async {
+      final AndroidEmulator emulator = AndroidEmulator(emulatorID);
+      expect(getEmulatorPath(androidSdk), mockSdk.emulatorPath);
+      final Completer<void> completer = Completer<void>();
+      FakeAsync().run((FakeAsync time) {
+        unawaited(emulator.launch().whenComplete(completer.complete));
+        time.elapse(const Duration(seconds: 5));
+        time.flushMicrotasks();
+      });
+      await completer.future;
+
+    }, overrides: <Type, Generator>{
+      ProcessManager: () => successProcessManager,
+      AndroidSdk: () => mockSdk,
+      FileSystem: () => fs,
+    });
+
+    testUsingContext('prints error on failure', () async {
+      final AndroidEmulator emulator = AndroidEmulator(emulatorID);
+      final Completer<void> completer = Completer<void>();
+      FakeAsync().run((FakeAsync time) {
+        unawaited(emulator.launch().whenComplete(completer.complete));
+        time.elapse(const Duration(seconds: 5));
+        time.flushMicrotasks();
+      });
+      await completer.future;
+
+      expect(testLogger.errorText, contains(errorText));
+    }, overrides: <Type, Generator>{
+      ProcessManager: () => errorProcessManager,
+      AndroidSdk: () => mockSdk,
+      FileSystem: () => fs,
+    });
+
+    testUsingContext('prints nothing on late failure with empty stderr', () async {
+      final AndroidEmulator emulator = AndroidEmulator(emulatorID);
+      final Completer<void> completer = Completer<void>();
+      FakeAsync().run((FakeAsync time) async {
+        unawaited(emulator.launch().whenComplete(completer.complete));
+        time.elapse(const Duration(seconds: 5));
+        time.flushMicrotasks();
+      });
+      await completer.future;
+      expect(testLogger.errorText, isEmpty);
+    }, overrides: <Type, Generator>{
+      ProcessManager: () => lateFailureProcessManager,
+      AndroidSdk: () => mockSdk,
+      FileSystem: () => fs,
+    });
+  });
 }
diff --git a/packages/flutter_tools/test/general.shard/android/gradle_test.dart b/packages/flutter_tools/test/general.shard/android/gradle_test.dart
index 265267a..cd3f773 100644
--- a/packages/flutter_tools/test/general.shard/android/gradle_test.dart
+++ b/packages/flutter_tools/test/general.shard/android/gradle_test.dart
@@ -1358,7 +1358,7 @@
           localGradleErrors: const <GradleHandledError>[],
         );
       },
-      throwsA(isInstanceOf<ProcessException>()));
+      throwsA(isA<ProcessException>()));
 
     }, overrides: <Type, Generator>{
       AndroidSdk: () => mockAndroidSdk,
diff --git a/packages/flutter_tools/test/general.shard/base/common_test.dart b/packages/flutter_tools/test/general.shard/base/common_test.dart
index 958e0ad..0ffb6c2 100644
--- a/packages/flutter_tools/test/general.shard/base/common_test.dart
+++ b/packages/flutter_tools/test/general.shard/base/common_test.dart
@@ -26,7 +26,7 @@
     });
 
     testWithoutContext('Throws if accessing the Zone', () {
-      expect(() => context.get<Object>(), throwsA(isInstanceOf<UnsupportedError>()));
+      expect(() => context.get<Object>(), throwsA(isA<UnsupportedError>()));
     });
   });
 }
diff --git a/packages/flutter_tools/test/general.shard/base/io_test.dart b/packages/flutter_tools/test/general.shard/base/io_test.dart
index c6778d0..603b07c 100644
--- a/packages/flutter_tools/test/general.shard/base/io_test.dart
+++ b/packages/flutter_tools/test/general.shard/base/io_test.dart
@@ -70,7 +70,7 @@
   });
 
   test('exit throws a StateError if called without being overriden', () {
-    expect(() => exit(0), throwsA(isInstanceOf<AssertionError>()));
+    expect(() => exit(0), throwsAssertionError);
   });
 
   test('exit does not throw a StateError if overriden', () {
diff --git a/packages/flutter_tools/test/general.shard/base/logger_test.dart b/packages/flutter_tools/test/general.shard/base/logger_test.dart
index 69921f6..e1c3374 100644
--- a/packages/flutter_tools/test/general.shard/base/logger_test.dart
+++ b/packages/flutter_tools/test/general.shard/base/logger_test.dart
@@ -182,8 +182,8 @@
           expect(lines.length, equals(1));
 
           // Verify that stopping or canceling multiple times throws.
-          expect(ansiSpinner.stop, throwsA(isInstanceOf<AssertionError>()));
-          expect(ansiSpinner.cancel, throwsA(isInstanceOf<AssertionError>()));
+          expect(ansiSpinner.stop, throwsAssertionError);
+          expect(ansiSpinner.cancel, throwsAssertionError);
           done = true;
         });
         expect(done, isTrue);
@@ -361,8 +361,8 @@
           expect(lines[1], equals(''));
 
           // Verify that stopping or canceling multiple times throws.
-          expect(() { ansiStatus.cancel(); }, throwsA(isInstanceOf<AssertionError>()));
-          expect(() { ansiStatus.stop(); }, throwsA(isInstanceOf<AssertionError>()));
+          expect(() { ansiStatus.cancel(); }, throwsAssertionError);
+          expect(() { ansiStatus.stop(); }, throwsAssertionError);
           done = true;
         });
         expect(done, isTrue);
@@ -405,8 +405,8 @@
           expect(lines[1], equals(''));
 
           // Verify that stopping or canceling multiple times throws.
-          expect(ansiStatus.stop, throwsA(isInstanceOf<AssertionError>()));
-          expect(ansiStatus.cancel, throwsA(isInstanceOf<AssertionError>()));
+          expect(ansiStatus.stop, throwsAssertionError);
+          expect(ansiStatus.cancel, throwsAssertionError);
           done = true;
         });
         expect(done, isTrue);
@@ -775,8 +775,8 @@
       expect(lines[1], equals(''));
 
       // Verify that stopping or canceling multiple times throws.
-      expect(summaryStatus.cancel, throwsA(isInstanceOf<AssertionError>()));
-      expect(summaryStatus.stop, throwsA(isInstanceOf<AssertionError>()));
+      expect(summaryStatus.cancel, throwsAssertionError);
+      expect(summaryStatus.stop, throwsAssertionError);
     });
 
     testWithoutContext('SummaryStatus works when stopped', () async {
@@ -798,8 +798,8 @@
       expect(lines[1], equals(''));
 
       // Verify that stopping or canceling multiple times throws.
-      expect(summaryStatus.stop, throwsA(isInstanceOf<AssertionError>()));
-      expect(summaryStatus.cancel, throwsA(isInstanceOf<AssertionError>()));
+      expect(summaryStatus.stop, throwsAssertionError);
+      expect(summaryStatus.cancel, throwsAssertionError);
     });
 
     testWithoutContext('sequential startProgress calls with StdoutLogger', () async {
diff --git a/packages/flutter_tools/test/general.shard/base/process_test.dart b/packages/flutter_tools/test/general.shard/base/process_test.dart
index 605d417..0259767 100644
--- a/packages/flutter_tools/test/general.shard/base/process_test.dart
+++ b/packages/flutter_tools/test/general.shard/base/process_test.dart
@@ -38,7 +38,7 @@
       when(mockProcessManager.run(<String>['false'])).thenAnswer(
           (Invocation invocation) => Future<ProcessResult>.value(ProcessResult(0, 1, '', '')));
       expect(() async => await processUtils.run(<String>['false'], throwOnError: true),
-             throwsA(isInstanceOf<ProcessException>()));
+             throwsA(isA<ProcessException>()));
     });
   });
 
@@ -236,7 +236,7 @@
         <String>['dummy'],
         timeout: delay - const Duration(milliseconds: 500),
         timeoutRetries: 0,
-      ), throwsA(isInstanceOf<ProcessException>()));
+      ), throwsA(isA<ProcessException>()));
     });
   });
 
diff --git a/packages/flutter_tools/test/general.shard/base/terminal_test.dart b/packages/flutter_tools/test/general.shard/base/terminal_test.dart
index 78bb1d4..d36b959 100644
--- a/packages/flutter_tools/test/general.shard/base/terminal_test.dart
+++ b/packages/flutter_tools/test/general.shard/base/terminal_test.dart
@@ -120,7 +120,7 @@
         <String>['a', 'b', 'c'],
         prompt: 'Please choose something',
         logger: null,
-      ), throwsA(isInstanceOf<StateError>()));
+      ), throwsStateError);
     });
 
     testWithoutContext('character prompt', () async {
diff --git a/packages/flutter_tools/test/general.shard/build_info_test.dart b/packages/flutter_tools/test/general.shard/build_info_test.dart
index 7aa13b9..fcd28ee 100644
--- a/packages/flutter_tools/test/general.shard/build_info_test.dart
+++ b/packages/flutter_tools/test/general.shard/build_info_test.dart
@@ -75,7 +75,7 @@
       expect(BuildMode.fromName('profile'), BuildMode.profile);
       expect(BuildMode.fromName('jit_release'), BuildMode.jitRelease);
       expect(BuildMode.fromName('release'), BuildMode.release);
-      expect(() => BuildMode.fromName('foo'), throwsA(isInstanceOf<ArgumentError>()));
+      expect(() => BuildMode.fromName('foo'), throwsArgumentError);
     });
   });
 }
diff --git a/packages/flutter_tools/test/general.shard/build_system/build_system_test.dart b/packages/flutter_tools/test/general.shard/build_system/build_system_test.dart
index 778fb59..6bc91d5 100644
--- a/packages/flutter_tools/test/general.shard/build_system/build_system_test.dart
+++ b/packages/flutter_tools/test/general.shard/build_system/build_system_test.dart
@@ -309,7 +309,7 @@
     barTarget.dependencies.add(fooTarget);
     fooTarget.dependencies.add(barTarget);
 
-    expect(() => checkCycles(barTarget), throwsA(isInstanceOf<CycleException>()));
+    expect(() => checkCycles(barTarget), throwsA(isA<CycleException>()));
   });
 
   test('Target with depfile dependency will not run twice without invalidation', () => testbed.run(() async {
diff --git a/packages/flutter_tools/test/general.shard/build_system/source_test.dart b/packages/flutter_tools/test/general.shard/build_system/source_test.dart
index a1dd81a..56e22bb 100644
--- a/packages/flutter_tools/test/general.shard/build_system/source_test.dart
+++ b/packages/flutter_tools/test/general.shard/build_system/source_test.dart
@@ -141,14 +141,14 @@
 
     globals.fs.file('abcd.bar').createSync();
 
-    expect(() => fizzSource.accept(visitor), throwsA(isInstanceOf<InvalidPatternException>()));
+    expect(() => fizzSource.accept(visitor), throwsA(isA<InvalidPatternException>()));
   }));
 
 
   test('can\'t substitute foo', () => testbed.run(() {
     const Source invalidBase = Source.pattern('foo');
 
-    expect(() => invalidBase.accept(visitor), throwsA(isInstanceOf<InvalidPatternException>()));
+    expect(() => invalidBase.accept(visitor), throwsA(isA<InvalidPatternException>()));
   }));
 
   test('can substitute optional files', () => testbed.run(() {
diff --git a/packages/flutter_tools/test/general.shard/build_system/targets/dart_test.dart b/packages/flutter_tools/test/general.shard/build_system/targets/dart_test.dart
index c3c9295..baa0699 100644
--- a/packages/flutter_tools/test/general.shard/build_system/targets/dart_test.dart
+++ b/packages/flutter_tools/test/general.shard/build_system/targets/dart_test.dart
@@ -113,7 +113,7 @@
     final BuildResult result = await buildSystem.build(const KernelSnapshot(),
         androidEnvironment..defines.remove(kBuildMode));
 
-    expect(result.exceptions.values.single.exception, isInstanceOf<MissingDefineException>());
+    expect(result.exceptions.values.single.exception, isA<MissingDefineException>());
   }));
 
   test('kernel_snapshot handles null result from kernel compilation', () => testbed.run(() async {
@@ -141,7 +141,7 @@
     });
     final BuildResult result = await buildSystem.build(const KernelSnapshot(), androidEnvironment);
 
-    expect(result.exceptions.values.single.exception, isInstanceOf<Exception>());
+    expect(result.exceptions.values.single.exception, isA<Exception>());
   }));
 
   test('kernel_snapshot does not use track widget creation on profile builds', () => testbed.run(() async {
@@ -283,35 +283,35 @@
     final BuildResult result = await buildSystem.build(const AotElfProfile(),
         androidEnvironment..defines.remove(kBuildMode));
 
-    expect(result.exceptions.values.single.exception, isInstanceOf<MissingDefineException>());
+    expect(result.exceptions.values.single.exception, isA<MissingDefineException>());
   }));
 
   test('aot_elf_profile throws error if missing target platform', () => testbed.run(() async {
     final BuildResult result = await buildSystem.build(const AotElfProfile(),
         androidEnvironment..defines.remove(kTargetPlatform));
 
-    expect(result.exceptions.values.single.exception, isInstanceOf<MissingDefineException>());
+    expect(result.exceptions.values.single.exception, isA<MissingDefineException>());
   }));
 
   test('aot_assembly_profile throws error if missing build mode', () => testbed.run(() async {
     final BuildResult result = await buildSystem.build(const AotAssemblyProfile(),
         iosEnvironment..defines.remove(kBuildMode));
 
-    expect(result.exceptions.values.single.exception, isInstanceOf<MissingDefineException>());
+    expect(result.exceptions.values.single.exception, isA<MissingDefineException>());
   }));
 
   test('aot_assembly_profile throws error if missing target platform', () => testbed.run(() async {
     final BuildResult result = await buildSystem.build(const AotAssemblyProfile(),
         iosEnvironment..defines.remove(kTargetPlatform));
 
-    expect(result.exceptions.values.single.exception, isInstanceOf<MissingDefineException>());
+    expect(result.exceptions.values.single.exception, isA<MissingDefineException>());
   }));
 
   test('aot_assembly_profile throws error if built for non-iOS platform', () => testbed.run(() async {
     final BuildResult result = await buildSystem
         .build(const AotAssemblyProfile(), androidEnvironment);
 
-    expect(result.exceptions.values.single.exception, isInstanceOf<Exception>());
+    expect(result.exceptions.values.single.exception, isA<Exception>());
   }));
 
   test('aot_assembly_profile will lipo binaries together when multiple archs are requested', () => testbed.run(() async {
diff --git a/packages/flutter_tools/test/general.shard/build_system/targets/macos_test.dart b/packages/flutter_tools/test/general.shard/build_system/targets/macos_test.dart
index e1efca9..f7d7912 100644
--- a/packages/flutter_tools/test/general.shard/build_system/targets/macos_test.dart
+++ b/packages/flutter_tools/test/general.shard/build_system/targets/macos_test.dart
@@ -128,7 +128,7 @@
       ..writeAsStringSync('testing');
 
     expect(() async => await const DebugMacOSBundleFlutterAssets().build(environment),
-        throwsA(isInstanceOf<Exception>()));
+        throwsException);
   }));
 
   test('debug macOS application creates correctly structured framework', () => testbed.run(() async {
diff --git a/packages/flutter_tools/test/general.shard/bundle_shim_test.dart b/packages/flutter_tools/test/general.shard/bundle_shim_test.dart
index 706bf73..770602b 100644
--- a/packages/flutter_tools/test/general.shard/bundle_shim_test.dart
+++ b/packages/flutter_tools/test/general.shard/bundle_shim_test.dart
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/build_info.dart';
 import 'package:flutter_tools/src/build_system/build_system.dart';
 import 'package:flutter_tools/src/bundle.dart';
@@ -62,7 +61,7 @@
       targetPlatform: TargetPlatform.linux_x64,
       depfilePath: 'example.d',
       precompiled: false,
-    ), throwsA(isInstanceOf<ToolExit>()));
+    ), throwsToolExit());
   }));
 }
 
diff --git a/packages/flutter_tools/test/general.shard/cache_test.dart b/packages/flutter_tools/test/general.shard/cache_test.dart
index adf3da9..65248b3 100644
--- a/packages/flutter_tools/test/general.shard/cache_test.dart
+++ b/packages/flutter_tools/test/general.shard/cache_test.dart
@@ -12,7 +12,6 @@
 import 'package:process/process.dart';
 
 import 'package:flutter_tools/src/android/gradle_utils.dart';
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/base/io.dart';
 import 'package:flutter_tools/src/cache.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
@@ -72,7 +71,7 @@
     testUsingContext('throws tool exit when lockfile open fails', () async {
       when(mockFileSystem.file(argThat(endsWith('lockfile')))).thenReturn(mockFile);
       when(mockFile.openSync(mode: anyNamed('mode'))).thenThrow(const FileSystemException());
-      expect(() async => await Cache.lock(), throwsA(isA<ToolExit>()));
+      expect(() async => await Cache.lock(), throwsToolExit());
     }, overrides: <Type, Generator>{
       FileSystem: () => mockFileSystem,
       ProcessManager: () => FakeProcessManager.any(),
@@ -248,7 +247,7 @@
         'FLUTTER_STORAGE_BASE_URL': ' http://foo',
       });
       final Cache cache = Cache();
-      expect(() => cache.storageBaseUrl, throwsA(isInstanceOf<ToolExit>()));
+      expect(() => cache.storageBaseUrl, throwsToolExit());
     }, overrides: <Type, Generator>{
       Platform: () => MockPlatform(),
     });
diff --git a/packages/flutter_tools/test/general.shard/compile_incremental_test.dart b/packages/flutter_tools/test/general.shard/compile_incremental_test.dart
index 9279c8b..79788ba 100644
--- a/packages/flutter_tools/test/general.shard/compile_incremental_test.dart
+++ b/packages/flutter_tools/test/general.shard/compile_incremental_test.dart
@@ -5,7 +5,6 @@
 import 'dart:async';
 
 import 'package:flutter_tools/src/base/async_guard.dart';
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/base/io.dart';
 import 'package:flutter_tools/src/base/terminal.dart';
 import 'package:flutter_tools/src/build_info.dart';
@@ -82,7 +81,7 @@
       '/path/to/main.dart',
       null, /* invalidatedFiles */
       outputPath: '/build/',
-    )), throwsA(isInstanceOf<ToolExit>()));
+    )), throwsToolExit());
   }, overrides: <Type, Generator>{
     ProcessManager: () => mockProcessManager,
     OutputPreferences: () => OutputPreferences(showColor: false),
@@ -100,7 +99,7 @@
       '/path/to/main.dart',
       null, /* invalidatedFiles */
       outputPath: '/build/',
-    )), throwsA(isInstanceOf<ToolExit>()));
+    )), throwsToolExit());
   }, overrides: <Type, Generator>{
     ProcessManager: () => mockProcessManager,
     OutputPreferences: () => OutputPreferences(showColor: false),
diff --git a/packages/flutter_tools/test/general.shard/compile_test.dart b/packages/flutter_tools/test/general.shard/compile_test.dart
index 412e9d5..7901a82 100644
--- a/packages/flutter_tools/test/general.shard/compile_test.dart
+++ b/packages/flutter_tools/test/general.shard/compile_test.dart
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/compile.dart';
 
 import '../src/common.dart';
@@ -25,7 +24,7 @@
     final Future<CompilerOutput> output = stdoutHandler.compilerOutput.future;
     stdoutHandler.handler('message with no result');
 
-    expect(output, throwsA(isInstanceOf<ToolExit>()));
+    expect(output, throwsToolExit());
   });
 
   test('TargetModel values', () {
@@ -41,6 +40,6 @@
     expect(TargetModel('dartdevc'), TargetModel.dartdevc);
     expect(TargetModel.dartdevc.toString(), 'dartdevc');
 
-    expect(() => TargetModel('foobar'), throwsA(isInstanceOf<AssertionError>()));
+    expect(() => TargetModel('foobar'), throwsAssertionError);
   });
 }
diff --git a/packages/flutter_tools/test/general.shard/dart/pub_get_test.dart b/packages/flutter_tools/test/general.shard/dart/pub_get_test.dart
index ff95577..f820969 100644
--- a/packages/flutter_tools/test/general.shard/dart/pub_get_test.dart
+++ b/packages/flutter_tools/test/general.shard/dart/pub_get_test.dart
@@ -328,7 +328,7 @@
         await pub.get(context: PubContext.flutterTests, checkLastModified: true);
         expect(true, isFalse, reason: 'pub.get did not throw');
       } catch (error) {
-        expect(error, isInstanceOf<Exception>());
+        expect(error, isA<Exception>());
         expect(error.message, '/: unexpected concurrent modification of pubspec.yaml while running pub.');
       }
       expect(testLogger.statusText, 'Running "flutter pub get" in /...\n');
diff --git a/packages/flutter_tools/test/general.shard/doctor.dart b/packages/flutter_tools/test/general.shard/doctor.dart
index 9f0913f..3839adf 100644
--- a/packages/flutter_tools/test/general.shard/doctor.dart
+++ b/packages/flutter_tools/test/general.shard/doctor.dart
@@ -20,9 +20,9 @@
 
   test('doctor validators includes desktop when features are enabled', () => testbed.run(() {
     expect(DoctorValidatorsProvider.defaultInstance.validators,
-        contains(isInstanceOf<LinuxDoctorValidator>()));
+        contains(isA<LinuxDoctorValidator>()));
     expect(DoctorValidatorsProvider.defaultInstance.validators,
-        contains(isInstanceOf<VisualStudioValidator>()));
+        contains(isA<VisualStudioValidator>()));
   }, overrides: <Type, Generator>{
     FeatureFlags: () => TestFeatureFlags(
       isLinuxEnabled: true,
@@ -32,9 +32,9 @@
 
   test('doctor validators does not include desktop when features are enabled', () => testbed.run(() {
     expect(DoctorValidatorsProvider.defaultInstance.validators,
-        isNot(contains(isInstanceOf<LinuxDoctorValidator>())));
+        isNot(contains(isA<LinuxDoctorValidator>())));
     expect(DoctorValidatorsProvider.defaultInstance.validators,
-        isNot(contains(isInstanceOf<VisualStudioValidator>())));
+        isNot(contains(isA<VisualStudioValidator>())));
   }, overrides: <Type, Generator>{
     FeatureFlags: () => TestFeatureFlags(
       isLinuxEnabled: false,
@@ -44,7 +44,7 @@
 
   test('doctor validators includes web when feature is enabled', () => testbed.run(() {
     expect(DoctorValidatorsProvider.defaultInstance.validators,
-        contains(isInstanceOf<WebValidator>()));
+        contains(isA<WebValidator>()));
   }, overrides: <Type, Generator>{
     FeatureFlags: () => TestFeatureFlags(
       isWebEnabled: true,
@@ -53,7 +53,7 @@
 
   test('doctor validators does not include web when feature is disabled', () => testbed.run(() {
     expect(DoctorValidatorsProvider.defaultInstance.validators,
-        isNot(contains(isInstanceOf<WebValidator>())));
+        isNot(contains(isA<WebValidator>())));
   }, overrides: <Type, Generator>{
     FeatureFlags: () => TestFeatureFlags(
       isWebEnabled: false,
diff --git a/packages/flutter_tools/test/general.shard/flutter_platform_test.dart b/packages/flutter_tools/test/general.shard/flutter_platform_test.dart
index fb9f9f1..13ef1af 100644
--- a/packages/flutter_tools/test/general.shard/flutter_platform_test.dart
+++ b/packages/flutter_tools/test/general.shard/flutter_platform_test.dart
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 import 'package:flutter_tools/src/build_info.dart';
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/base/io.dart';
 import 'package:flutter_tools/src/test/flutter_platform.dart';
 import 'package:meta/meta.dart';
@@ -21,13 +20,13 @@
     testUsingContext('ensureConfiguration throws an error if an explicitObservatoryPort is specified and more than one test file', () async {
       final FlutterPlatform flutterPlatform = FlutterPlatform(buildMode: BuildMode.debug, shellPath: '/', explicitObservatoryPort: 1234);
       flutterPlatform.loadChannel('test1.dart', MockSuitePlatform());
-      expect(() => flutterPlatform.loadChannel('test2.dart', MockSuitePlatform()), throwsA(isA<ToolExit>()));
+      expect(() => flutterPlatform.loadChannel('test2.dart', MockSuitePlatform()), throwsToolExit());
     });
 
     testUsingContext('ensureConfiguration throws an error if a precompiled entrypoint is specified and more that one test file', () {
       final FlutterPlatform flutterPlatform = FlutterPlatform(buildMode: BuildMode.debug, shellPath: '/', precompiledDillPath: 'example.dill');
       flutterPlatform.loadChannel('test1.dart', MockSuitePlatform());
-      expect(() => flutterPlatform.loadChannel('test2.dart', MockSuitePlatform()), throwsA(isA<ToolExit>()));
+      expect(() => flutterPlatform.loadChannel('test2.dart', MockSuitePlatform()), throwsToolExit());
     });
 
     group('The FLUTTER_TEST environment variable is passed to the test process', () {
@@ -50,7 +49,7 @@
         await untilCalled(mockProcessManager.start(any, environment: anyNamed('environment')));
         final VerificationResult toVerify = verify(mockProcessManager.start(any, environment: captureAnyNamed('environment')));
         expect(toVerify.captured, hasLength(1));
-        expect(toVerify.captured.first, isInstanceOf<Map<String, String>>());
+        expect(toVerify.captured.first, isA<Map<String, String>>());
         return toVerify.captured.first as Map<String, String>;
       }
 
@@ -91,7 +90,7 @@
         shellPath: 'abc',
         enableObservatory: false,
         startPaused: true,
-      ), throwsA(isA<AssertionError>()));
+      ), throwsAssertionError);
 
       expect(() => installHook(
         buildMode: BuildMode.debug,
@@ -99,7 +98,7 @@
         enableObservatory: false,
         startPaused: false,
         observatoryPort: 123,
-      ), throwsA(isA<AssertionError>()));
+      ), throwsAssertionError);
 
       FlutterPlatform capturedPlatform;
       final Map<String, String> expectedPrecompiledDillFiles = <String, String>{'Key': 'Value'};
diff --git a/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_device_test.dart b/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_device_test.dart
index 2810fcf..c0a2a0b 100644
--- a/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_device_test.dart
+++ b/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_device_test.dart
@@ -12,7 +12,6 @@
 import 'package:flutter_tools/src/base/context.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
 import 'package:flutter_tools/src/base/io.dart';
-import 'package:flutter_tools/src/base/process.dart';
 import 'package:flutter_tools/src/base/os.dart';
 import 'package:flutter_tools/src/base/time.dart';
 import 'package:flutter_tools/src/build_info.dart';
@@ -30,8 +29,8 @@
 import 'package:flutter_tools/src/vmservice.dart';
 import 'package:meta/meta.dart';
 import 'package:mockito/mockito.dart';
-import 'package:process/process.dart';
 import 'package:platform/platform.dart';
+import 'package:process/process.dart';
 
 import '../../src/common.dart';
 import '../../src/context.dart';
@@ -40,11 +39,10 @@
   group('fuchsia device', () {
     MemoryFileSystem memoryFileSystem;
     MockFile sshConfig;
-    MockProcessUtils mockProcessUtils;
+
     setUp(() {
       memoryFileSystem = MemoryFileSystem();
       sshConfig = MockFile();
-      mockProcessUtils = MockProcessUtils();
       when(sshConfig.absolute).thenReturn(sshConfig);
     });
 
@@ -118,27 +116,27 @@
     });
 
     testUsingContext('targetPlatform arm64 works', () async {
-      when(mockProcessUtils.run(any)).thenAnswer((Invocation _) {
-        return Future<RunResult>.value(RunResult(ProcessResult(1, 0, 'aarch64', ''), <String>['']));
+      when(globals.processManager.run(any)).thenAnswer((Invocation _) async {
+        return ProcessResult(1, 0, 'aarch64', '');
       });
       final FuchsiaDevice device = FuchsiaDevice('123');
       expect(await device.targetPlatform, TargetPlatform.fuchsia_arm64);
     }, overrides: <Type, Generator>{
       FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
       FuchsiaSdk: () => MockFuchsiaSdk(),
-      ProcessUtils: () => mockProcessUtils,
+      ProcessManager: () => MockProcessManager(),
     });
 
     testUsingContext('targetPlatform x64 works', () async {
-      when(mockProcessUtils.run(any)).thenAnswer((Invocation _) {
-        return Future<RunResult>.value(RunResult(ProcessResult(1, 0, 'x86_64', ''), <String>['']));
+      when(globals.processManager.run(any)).thenAnswer((Invocation _) async {
+        return ProcessResult(1, 0, 'x86_64', '');
       });
       final FuchsiaDevice device = FuchsiaDevice('123');
       expect(await device.targetPlatform, TargetPlatform.fuchsia_x64);
     }, overrides: <Type, Generator>{
       FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
       FuchsiaSdk: () => MockFuchsiaSdk(),
-      ProcessUtils: () => mockProcessUtils,
+      ProcessManager: () => MockProcessManager(),
     });
   });
 
@@ -326,8 +324,8 @@
     });
   });
 
-   group('screenshot', () {
-      MockProcessManager mockProcessManager;
+  group('screenshot', () {
+    MockProcessManager mockProcessManager;
 
     setUp(() {
       mockProcessManager = MockProcessManager();
@@ -550,6 +548,7 @@
     }, testOn: 'posix');
   });
 
+
   group(FuchsiaIsolateDiscoveryProtocol, () {
     MockPortForwarder portForwarder;
     MockVMService vmService;
@@ -960,8 +959,6 @@
 
 class MockProcessResult extends Mock implements ProcessResult {}
 
-class MockProcessUtils extends Mock implements ProcessUtils {}
-
 class MockFile extends Mock implements File {}
 
 class MockProcess extends Mock implements Process {}
diff --git a/packages/flutter_tools/test/general.shard/ios/devices_test.dart b/packages/flutter_tools/test/general.shard/ios/devices_test.dart
index fbf7ff0..74fb188 100644
--- a/packages/flutter_tools/test/general.shard/ios/devices_test.dart
+++ b/packages/flutter_tools/test/general.shard/ios/devices_test.dart
@@ -84,7 +84,7 @@
       testUsingContext('throws UnsupportedError exception if instantiated on ${platform.operatingSystem}', () {
         expect(
           () { IOSDevice('device-123'); },
-          throwsA(isInstanceOf<AssertionError>()),
+          throwsAssertionError,
         );
       }, overrides: <Type, Generator>{
         Platform: () => platform,
@@ -788,7 +788,7 @@
             .thenAnswer((Invocation invocation) => Future<String>.value(''));
         expect(
             () async { await IOSDevice.getAttachedDevices(); },
-            throwsA(isInstanceOf<UnsupportedError>()),
+            throwsA(isA<UnsupportedError>()),
         );
       }, overrides: <Type, Generator>{
         IMobileDevice: () => mockIMobileDevice,
diff --git a/packages/flutter_tools/test/general.shard/ios/mac_test.dart b/packages/flutter_tools/test/general.shard/ios/mac_test.dart
index ae846bf..0f2c9d7 100644
--- a/packages/flutter_tools/test/general.shard/ios/mac_test.dart
+++ b/packages/flutter_tools/test/general.shard/ios/mac_test.dart
@@ -108,7 +108,7 @@
         <String>[ideviceInfoPath, '-u', 'foo', '-k', 'bar'],
         environment: <String, String>{'DYLD_LIBRARY_PATH': libimobiledevicePath},
       )).thenAnswer((_) => Future<ProcessResult>.value(ProcessResult(1, 255, 'No device found with udid foo, is it plugged in?', '')));
-      expect(() async => await iMobileDevice.getInfoForDevice('foo', 'bar'), throwsA(isInstanceOf<IOSDeviceNotFoundError>()));
+      expect(() async => await iMobileDevice.getInfoForDevice('foo', 'bar'), throwsA(isA<IOSDeviceNotFoundError>()));
     }, overrides: <Type, Generator>{
       ProcessManager: () => mockProcessManager,
       Cache: () => mockCache,
@@ -129,7 +129,7 @@
         );
         return Future<ProcessResult>.value(result);
       });
-      expect(() async => await iMobileDevice.getInfoForDevice('foo', 'bar'), throwsA(isInstanceOf<IOSDeviceNotTrustedError>()));
+      expect(() async => await iMobileDevice.getInfoForDevice('foo', 'bar'), throwsA(isA<IOSDeviceNotTrustedError>()));
     }, overrides: <Type, Generator>{
       ProcessManager: () => mockProcessManager,
       Cache: () => mockCache,
@@ -171,7 +171,7 @@
         );
         return Future<ProcessResult>.value(result);
       });
-      expect(() async => await iMobileDevice.getInfoForDevice('foo', 'bar'), throwsA(isInstanceOf<IOSDeviceNotTrustedError>()));
+      expect(() async => await iMobileDevice.getInfoForDevice('foo', 'bar'), throwsA(isA<IOSDeviceNotTrustedError>()));
     }, overrides: <Type, Generator>{
       ProcessManager: () => mockProcessManager,
       Cache: () => mockCache,
diff --git a/packages/flutter_tools/test/general.shard/macos/cocoapods_test.dart b/packages/flutter_tools/test/general.shard/macos/cocoapods_test.dart
index ecd7e47..504a7dd 100644
--- a/packages/flutter_tools/test/general.shard/macos/cocoapods_test.dart
+++ b/packages/flutter_tools/test/general.shard/macos/cocoapods_test.dart
@@ -345,7 +345,7 @@
         );
         fail('ToolExit expected');
       } catch(e) {
-        expect(e, isInstanceOf<ToolExit>());
+        expect(e, isA<ToolExit>());
         verifyNever(mockProcessManager.run(
         argThat(containsAllInOrder(<String>['pod', 'install'])),
           workingDirectory: anyNamed('workingDirectory'),
@@ -394,7 +394,7 @@
         );
         fail('ToolExit expected');
       } catch (e) {
-        expect(e, isInstanceOf<ToolExit>());
+        expect(e, isA<ToolExit>());
         expect(
           testLogger.errorText,
           contains("CocoaPods's specs repository is too out-of-date to satisfy dependencies"),
diff --git a/packages/flutter_tools/test/general.shard/project_test.dart b/packages/flutter_tools/test/general.shard/project_test.dart
index 1fcdfe6..4a404b6 100644
--- a/packages/flutter_tools/test/general.shard/project_test.dart
+++ b/packages/flutter_tools/test/general.shard/project_test.dart
@@ -6,7 +6,6 @@
 
 import 'package:file/file.dart';
 import 'package:file/memory.dart';
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/base/context.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
 import 'package:flutter_tools/src/cache.dart';
@@ -29,7 +28,7 @@
       testInMemory('fails on null directory', () async {
         expect(
           () => FlutterProject.fromDirectory(null),
-          throwsA(isInstanceOf<AssertionError>()),
+          throwsAssertionError,
         );
       });
 
@@ -41,7 +40,7 @@
 
         expect(
           () => FlutterProject.fromDirectory(directory),
-          throwsA(isInstanceOf<ToolExit>()),
+          throwsToolExit(),
         );
       });
 
@@ -53,7 +52,7 @@
 
         expect(
           () => FlutterProject.fromDirectory(directory),
-          throwsA(isInstanceOf<ToolExit>()),
+          throwsToolExit(),
         );
       });
 
@@ -65,7 +64,7 @@
 
         expect(
           () => FlutterProject.fromDirectory(directory),
-          throwsA(isInstanceOf<ToolExit>()),
+          throwsToolExit(),
         );
       });
 
@@ -110,7 +109,7 @@
         final FlutterProject project = await someProject();
         await expectLater(
           project.android.makeHostAppEditable(),
-          throwsA(isInstanceOf<AssertionError>()),
+          throwsAssertionError,
         );
       });
       testInMemory('exits on already editable module', () async {
diff --git a/packages/flutter_tools/test/general.shard/resident_runner_test.dart b/packages/flutter_tools/test/general.shard/resident_runner_test.dart
index ef835f1..e576d2c 100644
--- a/packages/flutter_tools/test/general.shard/resident_runner_test.dart
+++ b/packages/flutter_tools/test/general.shard/resident_runner_test.dart
@@ -445,7 +445,7 @@
     when(mockDevice.supportsScreenshot).thenReturn(false);
 
     expect(() => residentRunner.screenshot(mockFlutterDevice),
-        throwsA(isInstanceOf<AssertionError>()));
+        throwsAssertionError);
   }));
 
   test('ResidentRunner does not toggle banner in non-debug mode', () => testbed.run(() async {
@@ -725,7 +725,7 @@
     expect(nextPlatform('iOS', TestFeatureFlags()), 'fuchsia');
     expect(nextPlatform('fuchsia', TestFeatureFlags()), 'android');
     expect(nextPlatform('fuchsia', TestFeatureFlags(isMacOSEnabled: true)), 'macOS');
-    expect(() => nextPlatform('unknown', TestFeatureFlags()), throwsA(isInstanceOf<AssertionError>()));
+    expect(() => nextPlatform('unknown', TestFeatureFlags()), throwsAssertionError);
   });
 }
 
diff --git a/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart b/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart
index 96698bf..d2b159c 100644
--- a/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart
+++ b/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart
@@ -82,6 +82,8 @@
           dartDefines: const <String>[],
           urlTunneller: null,
         ) as ResidentWebRunner;
+        globals.fs.currentDirectory.childFile('.packages')
+          ..writeAsStringSync('\n');
       },
       overrides: <Type, Generator>{
         WebFsFactory: () => ({
@@ -378,6 +380,8 @@
       pathToReload: anyNamed('pathToReload'),
       invalidatedFiles: anyNamed('invalidatedFiles'),
     )).thenAnswer((Invocation invocation) async {
+      // Generated entrypoint file in temp dir.
+      expect(invocation.namedArguments[#mainPath], contains('entrypoint.dart'));
       return UpdateFSReport(success: true)
         ..invalidatedModules = <String>['example'];
     });
@@ -926,7 +930,7 @@
 
     final Future<void> expectation = expectLater(() => residentWebRunner.run(
       connectionInfoCompleter: connectionInfoCompleter,
-    ), throwsA(isInstanceOf<ToolExit>()));
+    ), throwsToolExit());
 
     unhandledErrorCompleter.complete();
     await expectation;
@@ -945,7 +949,7 @@
 
     final Future<void> expectation = expectLater(() => residentWebRunner.run(
       connectionInfoCompleter: connectionInfoCompleter,
-    ), throwsA(isInstanceOf<ToolExit>()));
+    ), throwsToolExit());
 
     unhandledErrorCompleter.complete();
     await expectation;
@@ -964,7 +968,7 @@
 
     final Future<void> expectation = expectLater(() => residentWebRunner.run(
       connectionInfoCompleter: connectionInfoCompleter,
-    ), throwsA(isInstanceOf<ToolExit>()));
+    ), throwsToolExit());
 
     unhandledErrorCompleter.complete();
     await expectation;
@@ -983,7 +987,7 @@
 
     final Future<void> expectation = expectLater(() => residentWebRunner.run(
       connectionInfoCompleter: connectionInfoCompleter,
-    ), throwsA(isInstanceOf<ToolExit>()));
+    ), throwsToolExit());
 
     unhandledErrorCompleter.complete();
     await expectation;
@@ -1002,7 +1006,7 @@
 
     final Future<void> expectation = expectLater(() => residentWebRunner.run(
       connectionInfoCompleter: connectionInfoCompleter,
-    ), throwsA(isInstanceOf<ToolExit>()));
+    ), throwsToolExit());
 
     unhandledErrorCompleter.complete();
     await expectation;
@@ -1021,7 +1025,7 @@
 
     final Future<void> expectation = expectLater(() => residentWebRunner.run(
       connectionInfoCompleter: connectionInfoCompleter,
-    ), throwsA(isInstanceOf<ToolExit>()));
+    ), throwsToolExit());
 
     unhandledErrorCompleter.complete();
     await expectation;
@@ -1041,7 +1045,7 @@
 
     final Future<void> expectation = expectLater(() => residentWebRunner.run(
       connectionInfoCompleter: connectionInfoCompleter,
-    ), throwsA(isInstanceOf<Exception>()));
+    ), throwsException);
 
     unhandledErrorCompleter.complete();
     await expectation;
@@ -1060,7 +1064,7 @@
 
     final Future<void> expectation = expectLater(() => residentWebRunner.run(
       connectionInfoCompleter: connectionInfoCompleter,
-    ), throwsA(isInstanceOf<ToolExit>()));
+    ), throwsToolExit());
 
     unhandledErrorCompleter.complete();
     await expectation;
@@ -1082,7 +1086,7 @@
 
     final Future<void> expectation = expectLater(() => residentWebRunner.run(
       connectionInfoCompleter: connectionInfoCompleter,
-    ), throwsA(isInstanceOf<StateError>()));
+    ), throwsStateError);
 
     unhandledErrorCompleter.complete();
     await expectation;
diff --git a/packages/flutter_tools/test/general.shard/runner/flutter_command_runner_test.dart b/packages/flutter_tools/test/general.shard/runner/flutter_command_runner_test.dart
index 8cea9b0..e76b8b3 100644
--- a/packages/flutter_tools/test/general.shard/runner/flutter_command_runner_test.dart
+++ b/packages/flutter_tools/test/general.shard/runner/flutter_command_runner_test.dart
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 import 'package:file/memory.dart';
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/base/context.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
 import 'package:flutter_tools/src/base/io.dart';
@@ -92,7 +91,7 @@
         final MockFlutterVersion version = FlutterVersion.instance as MockFlutterVersion;
         when(version.ensureVersionFile()).thenThrow(const FileSystemException());
 
-        expect(() async => await runner.run(<String>['dummy']), throwsA(isA<ToolExit>()));
+        expect(() async => await runner.run(<String>['dummy']), throwsToolExit());
 
       }, overrides: <Type, Generator>{
         FileSystem: () => fs,
diff --git a/packages/flutter_tools/test/general.shard/terminal_handler_test.dart b/packages/flutter_tools/test/general.shard/terminal_handler_test.dart
index 9243191..57c1395 100644
--- a/packages/flutter_tools/test/general.shard/terminal_handler_test.dart
+++ b/packages/flutter_tools/test/general.shard/terminal_handler_test.dart
@@ -4,7 +4,6 @@
 
 import 'dart:async';
 
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/build_info.dart';
 import 'package:flutter_tools/src/device.dart';
 import 'package:flutter_tools/src/resident_runner.dart';
@@ -249,7 +248,7 @@
         .thenAnswer((Invocation invocation) async {
           return OperationResult(1, 'fail', fatal: true);
         });
-      expect(terminalHandler.processTerminalInput('r'), throwsA(isInstanceOf<ToolExit>()));
+      expect(terminalHandler.processTerminalInput('r'), throwsToolExit());
     });
 
     testUsingContext('r - hotReload unsupported', () async {
@@ -292,7 +291,7 @@
         .thenAnswer((Invocation invocation) async {
           return OperationResult(1, 'fail', fatal: true);
         });
-      expect(() => terminalHandler.processTerminalInput('R'), throwsA(isInstanceOf<ToolExit>()));
+      expect(() => terminalHandler.processTerminalInput('R'), throwsToolExit());
     });
 
     testUsingContext('R - hot restart unsupported', () async {
diff --git a/packages/flutter_tools/test/general.shard/testbed_test.dart b/packages/flutter_tools/test/general.shard/testbed_test.dart
index 6e10a6b..5735442 100644
--- a/packages/flutter_tools/test/general.shard/testbed_test.dart
+++ b/packages/flutter_tools/test/general.shard/testbed_test.dart
@@ -10,9 +10,11 @@
 import 'package:flutter_tools/src/base/context.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
 import 'package:flutter_tools/src/base/error_handling_file_system.dart';
+import 'package:flutter_tools/src/base/process.dart';
 import 'package:flutter_tools/src/globals.dart' as globals;
 
 import '../src/common.dart';
+import '../src/context.dart';
 import '../src/testbed.dart';
 
 void main() {
@@ -76,7 +78,7 @@
 
       expect(testbed.run(() async {
         Timer.periodic(const Duration(seconds: 1), (Timer timer) { });
-      }), throwsA(isInstanceOf<StateError>()));
+      }), throwsStateError);
     });
 
     test('Doesnt throw a StateError if Timer is left cleaned up', () async {
@@ -87,6 +89,14 @@
         timer.cancel();
       });
     });
+
+    test('Throws if ProcessUtils is injected',() {
+      final Testbed testbed = Testbed(overrides: <Type, Generator>{
+        ProcessUtils: () => null,
+      });
+
+      expect(() => testbed.run(() {}), throwsA(isInstanceOf<StateError>()));
+    });
   });
 }
 
diff --git a/packages/flutter_tools/test/general.shard/tester/flutter_tester_test.dart b/packages/flutter_tools/test/general.shard/tester/flutter_tester_test.dart
index ea2eed1..86beb37 100644
--- a/packages/flutter_tools/test/general.shard/tester/flutter_tester_test.dart
+++ b/packages/flutter_tools/test/general.shard/tester/flutter_tester_test.dart
@@ -61,7 +61,7 @@
       expect(devices, hasLength(1));
 
       final Device device = devices.single;
-      expect(device, isInstanceOf<FlutterTesterDevice>());
+      expect(device, isA<FlutterTesterDevice>());
       expect(device.id, 'flutter-tester');
     });
   });
diff --git a/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart b/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart
index 1c9878a..8f255ac 100644
--- a/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart
+++ b/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart
@@ -5,7 +5,6 @@
 import 'dart:async';
 import 'dart:io';
 
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
 import 'package:flutter_tools/src/base/io.dart';
 import 'package:flutter_tools/src/convert.dart';
@@ -80,7 +79,7 @@
   });
 
   test('Throws a tool exit if bind fails with a SocketException', () => testbed.run(() async {
-    expect(WebAssetServer.start('hello', 1234), throwsA(isInstanceOf<ToolExit>()));
+    expect(WebAssetServer.start('hello', 1234), throwsToolExit());
   }));
 
   test('Can catch exceptions through the onError callback', () => testbed.run(() async {
@@ -92,7 +91,7 @@
     when(request.uri).thenReturn(Uri.parse('http://foobar/foo.js'));
     requestController.add(request);
 
-    expect(closeCompleter.future, throwsA(isInstanceOf<StateError>()));
+    expect(closeCompleter.future, throwsStateError);
   }));
 
   test('Handles against malformed manifest', () => testbed.run(() async {
diff --git a/packages/flutter_tools/test/general.shard/web/devices_test.dart b/packages/flutter_tools/test/general.shard/web/devices_test.dart
index 47958a7..f3c0d51 100644
--- a/packages/flutter_tools/test/general.shard/web/devices_test.dart
+++ b/packages/flutter_tools/test/general.shard/web/devices_test.dart
@@ -41,8 +41,8 @@
     expect(chromeDevice.supportsFlutterExit, true);
     expect(chromeDevice.supportsScreenshot, false);
     expect(await chromeDevice.isLocalEmulator, false);
-    expect(chromeDevice.getLogReader(app: mockWebApplicationPackage), isInstanceOf<NoOpDeviceLogReader>());
-    expect(chromeDevice.getLogReader(), isInstanceOf<NoOpDeviceLogReader>());
+    expect(chromeDevice.getLogReader(app: mockWebApplicationPackage), isA<NoOpDeviceLogReader>());
+    expect(chromeDevice.getLogReader(), isA<NoOpDeviceLogReader>());
     expect(await chromeDevice.portForwarder.forward(1), 1);
   });
 
@@ -57,8 +57,8 @@
     expect(device.supportsFlutterExit, true);
     expect(device.supportsScreenshot, false);
     expect(await device.isLocalEmulator, false);
-    expect(device.getLogReader(app: mockWebApplicationPackage), isInstanceOf<NoOpDeviceLogReader>());
-    expect(device.getLogReader(), isInstanceOf<NoOpDeviceLogReader>());
+    expect(device.getLogReader(app: mockWebApplicationPackage), isA<NoOpDeviceLogReader>());
+    expect(device.getLogReader(), isA<NoOpDeviceLogReader>());
     expect(await device.portForwarder.forward(1), 1);
   });
 
@@ -67,7 +67,7 @@
 
     final WebDevices deviceDiscoverer = WebDevices();
     final List<Device> devices = await deviceDiscoverer.pollingGetDevices();
-    expect(devices, contains(isInstanceOf<ChromeDevice>()));
+    expect(devices, contains(isA<ChromeDevice>()));
   }, overrides: <Type, Generator>{
     ChromeLauncher: () => mockChromeLauncher,
   });
@@ -77,7 +77,7 @@
 
     final WebDevices deviceDiscoverer = WebDevices();
     final List<Device> devices = await deviceDiscoverer.pollingGetDevices();
-    expect(devices, isNot(contains(isInstanceOf<ChromeDevice>())));
+    expect(devices, isNot(contains(isA<ChromeDevice>())));
   }, overrides: <Type, Generator>{
     ChromeLauncher: () => mockChromeLauncher,
   });
@@ -87,7 +87,7 @@
 
     final WebDevices deviceDiscoverer = WebDevices();
     final List<Device> devices = await deviceDiscoverer.pollingGetDevices();
-    expect(devices, contains(isInstanceOf<WebServerDevice>()));
+    expect(devices, contains(isA<WebServerDevice>()));
   }, overrides: <Type, Generator>{
     ChromeLauncher: () => mockChromeLauncher,
   });
diff --git a/packages/flutter_tools/test/general.shard/web/web_fs_test.dart b/packages/flutter_tools/test/general.shard/web/web_fs_test.dart
index b4ab4f4..9645022 100644
--- a/packages/flutter_tools/test/general.shard/web/web_fs_test.dart
+++ b/packages/flutter_tools/test/general.shard/web/web_fs_test.dart
@@ -8,7 +8,6 @@
 import 'package:dwds/asset_handler.dart';
 import 'package:dwds/dwds.dart';
 import 'package:flutter_tools/src/base/os.dart';
-import 'package:flutter_tools/src/base/process.dart';
 import 'package:flutter_tools/src/build_info.dart';
 import 'package:flutter_tools/src/dart/pub.dart';
 import 'package:flutter_tools/src/project.dart';
@@ -18,8 +17,10 @@
 import 'package:http_multi_server/http_multi_server.dart';
 import 'package:meta/meta.dart';
 import 'package:mockito/mockito.dart';
+import 'package:process/process.dart';
 
 import '../../src/common.dart';
+import '../../src/mocks.dart';
 import '../../src/testbed.dart';
 
 void main() {
@@ -30,7 +31,7 @@
   MockHttpMultiServer mockHttpMultiServer;
   MockBuildDaemonClient mockBuildDaemonClient;
   MockOperatingSystemUtils mockOperatingSystemUtils;
-  MockProcessUtils mockProcessUtils;
+  MockProcessManager mockProcessManager;
   bool lastInitializePlatform;
   int lastPort;
 
@@ -43,7 +44,7 @@
     mockBuildDaemonClient = MockBuildDaemonClient();
     mockOperatingSystemUtils = MockOperatingSystemUtils();
     mockDwds = MockDwds();
-    mockProcessUtils = MockProcessUtils();
+    mockProcessManager = MockProcessManager();
     when(mockBuildDaemonCreator.startBuildDaemon(any, release: anyNamed('release'), initializePlatform: anyNamed('initializePlatform')))
       .thenAnswer((Invocation invocation) async {
         lastInitializePlatform = invocation.namedArguments[#initializePlatform] as bool;
@@ -52,15 +53,14 @@
     when(mockOperatingSystemUtils.findFreePort()).thenAnswer((Invocation _) async {
       return 1234;
     });
-    when(mockProcessUtils.stream(
+    when(mockProcessManager.start(
       any,
       workingDirectory: anyNamed('workingDirectory'),
-      mapFunction: anyNamed('mapFunction'),
       environment: anyNamed('environment'),
     )).thenAnswer((Invocation invocation) async {
       final String workingDirectory = invocation.namedArguments[#workingDirectory] as String;
       globals.fs.file(globals.fs.path.join(workingDirectory, '.packages')).createSync(recursive: true);
-      return 0;
+      return FakeProcess();
     });
     when(mockBuildDaemonClient.buildResults).thenAnswer((Invocation _) {
       return Stream<BuildResults>.fromFuture(Future<BuildResults>.value(
@@ -91,7 +91,7 @@
         OperatingSystemUtils: () => mockOperatingSystemUtils,
         BuildDaemonCreator: () => mockBuildDaemonCreator,
         ChromeLauncher: () => mockChromeLauncher,
-        ProcessUtils: () => mockProcessUtils,
+        ProcessManager: () => mockProcessManager,
         HttpMultiServerFactory: () => (dynamic address, int port) async {
           lastPort = port;
           return mockHttpMultiServer;
@@ -215,7 +215,7 @@
       port: '1234',
       urlTunneller: null,
       dartDefines: const <String>[],
-    ), throwsA(isInstanceOf<Exception>()));
+    ), throwsException);
   }));
 }
 
@@ -225,5 +225,5 @@
 class MockHttpMultiServer extends Mock implements HttpMultiServer {}
 class MockChromeLauncher extends Mock implements ChromeLauncher {}
 class MockOperatingSystemUtils extends Mock implements OperatingSystemUtils {}
-class MockProcessUtils extends Mock implements ProcessUtils {}
 class MockPub extends Mock implements Pub {}
+class MockProcessManager extends Mock implements ProcessManager {}
diff --git a/packages/flutter_tools/test/src/common.dart b/packages/flutter_tools/test/src/common.dart
index 419674a..fb446bc 100644
--- a/packages/flutter_tools/test/src/common.dart
+++ b/packages/flutter_tools/test/src/common.dart
@@ -22,7 +22,7 @@
 
 /// A matcher that compares the type of the actual value to the type argument T.
 // TODO(ianh): Remove this once https://github.com/dart-lang/matcher/issues/98 is fixed
-Matcher isInstanceOf<T>() => test_package.TypeMatcher<T>();
+test_package.TypeMatcher<T> isInstanceOf<T>() => isA<T>();
 
 void tryToDelete(Directory directory) {
   // This should not be necessary, but it turns out that
@@ -91,6 +91,9 @@
   globals.fs.file(path).setLastModifiedSync(modificationTime);
 }
 
+/// Matcher for functions that throw [AssertionError].
+final Matcher throwsAssertionError = throwsA(isA<AssertionError>());
+
 /// Matcher for functions that throw [ToolExit].
 Matcher throwsToolExit({ int exitCode, Pattern message }) {
   Matcher matcher = isToolExit;
@@ -104,7 +107,7 @@
 }
 
 /// Matcher for [ToolExit]s.
-final Matcher isToolExit = isInstanceOf<ToolExit>();
+final test_package.TypeMatcher<ToolExit> isToolExit = isA<ToolExit>();
 
 /// Matcher for functions that throw [ProcessExit].
 Matcher throwsProcessExit([ dynamic exitCode ]) {
@@ -114,7 +117,7 @@
 }
 
 /// Matcher for [ProcessExit]s.
-final Matcher isProcessExit = isInstanceOf<ProcessExit>();
+final test_package.TypeMatcher<ProcessExit> isProcessExit = isA<ProcessExit>();
 
 /// Creates a flutter project in the [temp] directory using the
 /// [arguments] list if specified, or `--no-pub` if not.
diff --git a/packages/flutter_tools/test/src/context.dart b/packages/flutter_tools/test/src/context.dart
index 80d2d30..ad67944 100644
--- a/packages/flutter_tools/test/src/context.dart
+++ b/packages/flutter_tools/test/src/context.dart
@@ -12,6 +12,7 @@
 import 'package:flutter_tools/src/base/io.dart';
 import 'package:flutter_tools/src/base/logger.dart';
 import 'package:flutter_tools/src/base/os.dart';
+import 'package:flutter_tools/src/base/process.dart';
 import 'package:flutter_tools/src/base/signals.dart';
 import 'package:flutter_tools/src/base/terminal.dart';
 import 'package:flutter_tools/src/base/time.dart';
@@ -63,6 +64,9 @@
       'that you are dealing with in your test.'
     );
   }
+  if (overrides.containsKey(ProcessUtils)) {
+    throw StateError('Do not inject ProcessUtils for testing, use ProcessManager instead.');
+  }
 
   // Ensure we don't rely on the default [Config] constructor which will
   // leak a sticky $HOME/.flutter_settings behind!
diff --git a/packages/flutter_tools/test/src/testbed.dart b/packages/flutter_tools/test/src/testbed.dart
index 5934d28..4bd9694 100644
--- a/packages/flutter_tools/test/src/testbed.dart
+++ b/packages/flutter_tools/test/src/testbed.dart
@@ -12,6 +12,7 @@
 import 'package:flutter_tools/src/base/io.dart';
 import 'package:flutter_tools/src/base/logger.dart';
 import 'package:flutter_tools/src/base/os.dart';
+import 'package:flutter_tools/src/base/process.dart';
 
 import 'package:flutter_tools/src/base/signals.dart';
 import 'package:flutter_tools/src/base/terminal.dart';
@@ -113,6 +114,9 @@
       // Add the test-specific overrides
       ...?overrides,
     };
+    if (testOverrides.containsKey(ProcessUtils)) {
+      throw StateError('Do not inject ProcessUtils for testing, use ProcessManager instead.');
+    }
     // Cache the original flutter root to restore after the test case.
     final String originalFlutterRoot = Cache.flutterRoot;
     // Track pending timers to verify that they were correctly cleaned up.
diff --git a/packages/flutter_tools/test/template_test.dart b/packages/flutter_tools/test/template_test.dart
index 2aedd4e..936cf57 100644
--- a/packages/flutter_tools/test/template_test.dart
+++ b/packages/flutter_tools/test/template_test.dart
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
 import 'package:flutter_tools/src/template.dart';
 import 'package:flutter_tools/src/globals.dart' as globals;
@@ -24,7 +23,7 @@
     when(mockDirectory.createSync(recursive: true)).thenThrow(const FileSystemException());
 
     expect(() => template.render(mockDirectory, <String, Object>{}),
-        throwsA(isInstanceOf<ToolExit>()));
+        throwsToolExit());
   }));
 }