[camera] Update [CameraOrientationTests testOrientationNotifications] unit test to work on Xcode 13 (#4426)

diff --git a/packages/camera/camera/CHANGELOG.md b/packages/camera/camera/CHANGELOG.md
index c9dfc63..dc83a4f 100644
--- a/packages/camera/camera/CHANGELOG.md
+++ b/packages/camera/camera/CHANGELOG.md
@@ -1,6 +1,7 @@
-## NEXT
+## 0.9.4+2
 
-* Updated package description.
+* Updated package description;
+* Refactor unit test on iOS to make it compatible with new restrictions in Xcode 13 which only supports the use of the `XCUIDevice` in Xcode UI tests.
 
 ## 0.9.4+1
 
diff --git a/packages/camera/camera/example/ios/RunnerTests/CameraOrientationTests.m b/packages/camera/camera/example/ios/RunnerTests/CameraOrientationTests.m
index 6c29ef7..246eab9 100644
--- a/packages/camera/camera/example/ios/RunnerTests/CameraOrientationTests.m
+++ b/packages/camera/camera/example/ios/RunnerTests/CameraOrientationTests.m
@@ -3,30 +3,29 @@
 // found in the LICENSE file.
 
 @import camera;
+@import camera.Test;
 @import XCTest;
+@import Flutter;
 
 #import <OCMock/OCMock.h>
 
 @interface CameraOrientationTests : XCTestCase
-@property(strong, nonatomic) id mockRegistrar;
 @property(strong, nonatomic) id mockMessenger;
+@property(strong, nonatomic) CameraPlugin *cameraPlugin;
 @end
 
 @implementation CameraOrientationTests
 
 - (void)setUp {
   [super setUp];
-  self.mockRegistrar = OCMProtocolMock(@protocol(FlutterPluginRegistrar));
+
   self.mockMessenger = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
-  OCMStub([self.mockRegistrar messenger]).andReturn(self.mockMessenger);
+  self.cameraPlugin = [[CameraPlugin alloc] initWithRegistry:nil messenger:self.mockMessenger];
 }
 
 - (void)testOrientationNotifications {
   id mockMessenger = self.mockMessenger;
   [mockMessenger setExpectationOrderMatters:YES];
-  XCUIDevice.sharedDevice.orientation = UIDeviceOrientationPortrait;
-
-  [CameraPlugin registerWithRegistrar:self.mockRegistrar];
 
   [self rotate:UIDeviceOrientationPortraitUpsideDown expectedChannelOrientation:@"portraitDown"];
   [self rotate:UIDeviceOrientationPortrait expectedChannelOrientation:@"portraitUp"];
@@ -34,34 +33,43 @@
   [self rotate:UIDeviceOrientationLandscapeLeft expectedChannelOrientation:@"landscapeRight"];
 
   OCMReject([mockMessenger sendOnChannel:[OCMArg any] message:[OCMArg any]]);
-  // No notification when orientation doesn't change.
-  XCUIDevice.sharedDevice.orientation = UIDeviceOrientationLandscapeLeft;
+
   // No notification when flat.
-  XCUIDevice.sharedDevice.orientation = UIDeviceOrientationFaceUp;
+  [self.cameraPlugin
+      orientationChanged:[self createMockNotificationForOrientation:UIDeviceOrientationFaceUp]];
   // No notification when facedown.
-  XCUIDevice.sharedDevice.orientation = UIDeviceOrientationFaceDown;
+  [self.cameraPlugin
+      orientationChanged:[self createMockNotificationForOrientation:UIDeviceOrientationFaceDown]];
 
   OCMVerifyAll(mockMessenger);
 }
 
 - (void)rotate:(UIDeviceOrientation)deviceOrientation
-    expectedChannelOrientation:(NSString*)channelOrientation {
+    expectedChannelOrientation:(NSString *)channelOrientation {
   id mockMessenger = self.mockMessenger;
-  XCTestExpectation* orientationExpectation = [self expectationWithDescription:channelOrientation];
+  XCTestExpectation *orientationExpectation = [self expectationWithDescription:channelOrientation];
 
   OCMExpect([mockMessenger
       sendOnChannel:[OCMArg any]
-            message:[OCMArg checkWithBlock:^BOOL(NSData* data) {
-              NSObject<FlutterMethodCodec>* codec = [FlutterStandardMethodCodec sharedInstance];
-              FlutterMethodCall* methodCall = [codec decodeMethodCall:data];
+            message:[OCMArg checkWithBlock:^BOOL(NSData *data) {
+              NSObject<FlutterMethodCodec> *codec = [FlutterStandardMethodCodec sharedInstance];
+              FlutterMethodCall *methodCall = [codec decodeMethodCall:data];
               [orientationExpectation fulfill];
               return
                   [methodCall.method isEqualToString:@"orientation_changed"] &&
                   [methodCall.arguments isEqualToDictionary:@{@"orientation" : channelOrientation}];
             }]]);
 
-  XCUIDevice.sharedDevice.orientation = deviceOrientation;
+  [self.cameraPlugin
+      orientationChanged:[self createMockNotificationForOrientation:deviceOrientation]];
   [self waitForExpectationsWithTimeout:30.0 handler:nil];
 }
 
+- (NSNotification *)createMockNotificationForOrientation:(UIDeviceOrientation)deviceOrientation {
+  UIDevice *mockDevice = OCMClassMock([UIDevice class]);
+  OCMStub([mockDevice orientation]).andReturn(deviceOrientation);
+
+  return [NSNotification notificationWithName:@"orientation_test" object:mockDevice];
+}
+
 @end
diff --git a/packages/camera/camera/ios/Classes/CameraPlugin.m b/packages/camera/camera/ios/Classes/CameraPlugin.m
index da560d6..78c5a34 100644
--- a/packages/camera/camera/ios/Classes/CameraPlugin.m
+++ b/packages/camera/camera/ios/Classes/CameraPlugin.m
@@ -3,6 +3,8 @@
 // found in the LICENSE file.
 
 #import "CameraPlugin.h"
+#import "CameraPlugin_Test.h"
+
 #import <AVFoundation/AVFoundation.h>
 #import <Accelerate/Accelerate.h>
 #import <CoreMotion/CoreMotion.h>
diff --git a/packages/camera/camera/ios/Classes/CameraPlugin.modulemap b/packages/camera/camera/ios/Classes/CameraPlugin.modulemap
new file mode 100644
index 0000000..30afa91
--- /dev/null
+++ b/packages/camera/camera/ios/Classes/CameraPlugin.modulemap
@@ -0,0 +1,10 @@
+framework module camera {
+  umbrella header "camera-umbrella.h"
+
+  export *
+  module * { export * }
+
+  explicit module Test {
+    header "CameraPlugin_Test.h"
+  }
+}
diff --git a/packages/camera/camera/ios/Classes/CameraPlugin_Test.h b/packages/camera/camera/ios/Classes/CameraPlugin_Test.h
new file mode 100644
index 0000000..6952ae0
--- /dev/null
+++ b/packages/camera/camera/ios/Classes/CameraPlugin_Test.h
@@ -0,0 +1,19 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This header is available in the Test module. Import via "@import camera.Test;"
+
+#import <camera/CameraPlugin.h>
+
+/// Methods exposed for unit testing.
+@interface CameraPlugin ()
+
+- (instancetype)initWithRegistry:(NSObject<FlutterTextureRegistry> *)registry
+                       messenger:(NSObject<FlutterBinaryMessenger> *)messenger
+    NS_DESIGNATED_INITIALIZER;
+- (instancetype)init NS_UNAVAILABLE;
+
+- (void)orientationChanged:(NSNotification *)notification;
+
+@end
diff --git a/packages/camera/camera/ios/Classes/camera-umbrella.h b/packages/camera/camera/ios/Classes/camera-umbrella.h
new file mode 100644
index 0000000..5c39401
--- /dev/null
+++ b/packages/camera/camera/ios/Classes/camera-umbrella.h
@@ -0,0 +1,9 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Foundation/Foundation.h>
+#import <camera/CameraPlugin.h>
+
+FOUNDATION_EXPORT double cameraVersionNumber;
+FOUNDATION_EXPORT const unsigned char cameraVersionString[];
diff --git a/packages/camera/camera/ios/camera.podspec b/packages/camera/camera/ios/camera.podspec
index 4a142bd..5906bf9 100644
--- a/packages/camera/camera/ios/camera.podspec
+++ b/packages/camera/camera/ios/camera.podspec
@@ -13,8 +13,9 @@
   s.author           = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' }
   s.source           = { :http => 'https://github.com/flutter/plugins/tree/master/packages/camera' }
   s.documentation_url = 'https://pub.dev/packages/camera'
-  s.source_files = 'Classes/**/*'
+  s.source_files = 'Classes/**/*.{h,m}'
   s.public_header_files = 'Classes/**/*.h'
+  s.module_map = 'Classes/CameraPlugin.modulemap'
   s.dependency 'Flutter'
 
   s.platform = :ios, '9.0'
diff --git a/packages/camera/camera/pubspec.yaml b/packages/camera/camera/pubspec.yaml
index 21892b2..f68d026 100644
--- a/packages/camera/camera/pubspec.yaml
+++ b/packages/camera/camera/pubspec.yaml
@@ -4,7 +4,7 @@
   Dart.
 repository: https://github.com/flutter/plugins/tree/master/packages/camera/camera
 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22
-version: 0.9.4+1
+version: 0.9.4+2
 
 environment:
   sdk: ">=2.14.0 <3.0.0"