Refactor exits happy (#52916)

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 7d5b17a..27569b1 100644
--- a/packages/flutter_tools/test/general.shard/base/process_test.dart
+++ b/packages/flutter_tools/test/general.shard/base/process_test.dart
@@ -336,7 +336,7 @@
   });
 
   group('exitsHappySync', () {
-    ProcessManager mockProcessManager;
+    MockProcessManager mockProcessManager;
     ProcessUtils processUtils;
 
     setUp(() {
@@ -368,16 +368,27 @@
       expect(processUtils.exitsHappySync(<String>['boohoo']), isFalse);
     });
 
-    testWithoutContext('catches ArgumentError and returns false', () {
-      when(mockProcessManager.runSync(<String>['nonesuch'])).thenThrow(
-        ArgumentError('Invalid argument(s): Cannot find executable for nonesuch')
-      );
+    testWithoutContext('does not throw Exception and returns false if binary cannot run', () {
+      mockProcessManager.canRunSucceeds = false;
       expect(processUtils.exitsHappySync(<String>['nonesuch']), isFalse);
+      verifyNever(
+        mockProcessManager.runSync(any, environment: anyNamed('environment')),
+      );
+    });
+
+    testWithoutContext('does not catch ArgumentError', () async {
+      when(mockProcessManager.runSync(<String>['invalid'])).thenThrow(
+        ArgumentError('Bad input'),
+      );
+      expect(
+        () => processUtils.exitsHappySync(<String>['invalid']),
+        throwsArgumentError,
+      );
     });
   });
 
   group('exitsHappy', () {
-    ProcessManager mockProcessManager;
+    MockProcessManager mockProcessManager;
     ProcessUtils processUtils;
 
     setUp(() {
@@ -388,14 +399,14 @@
       );
     });
 
-    testWithoutContext(' succeeds on success', () async {
+    testWithoutContext('succeeds on success', () async {
       when(mockProcessManager.run(<String>['whoohoo'])).thenAnswer((_) {
         return Future<ProcessResult>.value(ProcessResult(0, 0, '', ''));
       });
       expect(await processUtils.exitsHappy(<String>['whoohoo']), isTrue);
     });
 
-    testWithoutContext(' fails on failure', () async {
+    testWithoutContext('fails on failure', () async {
       when(mockProcessManager.run(<String>['boohoo'])).thenAnswer((_) {
         return Future<ProcessResult>.value(ProcessResult(0, 1, '', ''));
       });
@@ -409,11 +420,22 @@
       expect(await processUtils.exitsHappy(<String>['boohoo']), isFalse);
     });
 
-    testWithoutContext('catches ArgumentError and returns false', () async {
-      when(mockProcessManager.run(<String>['nonesuch'])).thenThrow(
-        ArgumentError('Invalid argument(s): Cannot find executable for nonesuch'),
-      );
+    testWithoutContext('does not throw Exception and returns false if binary cannot run', () async {
+      mockProcessManager.canRunSucceeds = false;
       expect(await processUtils.exitsHappy(<String>['nonesuch']), isFalse);
+      verifyNever(
+        mockProcessManager.runSync(any, environment: anyNamed('environment')),
+      );
+    });
+
+    testWithoutContext('does not catch ArgumentError', () async {
+      when(mockProcessManager.run(<String>['invalid'])).thenThrow(
+        ArgumentError('Bad input'),
+      );
+      expect(
+        () async => await processUtils.exitsHappy(<String>['invalid']),
+        throwsArgumentError,
+      );
     });
   });
 
diff --git a/packages/flutter_tools/test/general.shard/ios/code_signing_test.dart b/packages/flutter_tools/test/general.shard/ios/code_signing_test.dart
index f00d5aa..60e7650 100644
--- a/packages/flutter_tools/test/general.shard/ios/code_signing_test.dart
+++ b/packages/flutter_tools/test/general.shard/ios/code_signing_test.dart
@@ -30,6 +30,8 @@
 
     setUp(() async {
       mockProcessManager = MockProcessManager();
+      // Assume all binaries exist and are executable
+      when(mockProcessManager.canRun(any)).thenReturn(true);
       mockConfig = MockConfig();
       mockIosProject = MockIosProject();
       when(mockIosProject.buildSettings).thenAnswer((_) {
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 b1e78a4..fbba453 100644
--- a/packages/flutter_tools/test/general.shard/macos/cocoapods_test.dart
+++ b/packages/flutter_tools/test/general.shard/macos/cocoapods_test.dart
@@ -134,6 +134,11 @@
   }
 
   group('Evaluate installation', () {
+    setUp(() {
+      // Assume all binaries can run
+      when(mockProcessManager.canRun(any)).thenReturn(true);
+    });
+
     testUsingContext('detects not installed, if pod exec does not exist', () async {
       pretendPodIsNotInstalled();
       expect(await cocoaPodsUnderTest.evaluateCocoaPodsInstallation, CocoaPodsStatus.notInstalled);
@@ -328,6 +333,8 @@
   group('Process pods', () {
     setUp(() {
       podsIsInHomeDir();
+      // Assume all binaries can run
+      when(mockProcessManager.canRun(any)).thenReturn(true);
     });
 
     testUsingContext('throwsToolExit if CocoaPods is not installed', () async {
@@ -674,6 +681,8 @@
     String cocoapodsRepoDir;
     Map<String, String> environment;
     setUp(() {
+      // Assume binaries exist and can run
+      when(mockProcessManager.canRun(any)).thenReturn(true);
       cocoapodsRepoDir = podsIsInCustomDir();
       environment = <String, String>{
         'FLUTTER_FRAMEWORK_DIR': 'engine/path',