FIRAppCheckTests.m 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. /*
  2. * Copyright 2020 Google LLC
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #import <XCTest/XCTest.h>
  17. #import <OCMock/OCMock.h>
  18. #import <FirebaseAppCheckInterop/FirebaseAppCheckInterop.h>
  19. #import "FirebaseAppCheck/Sources/Public/FirebaseAppCheck/FIRAppCheck.h"
  20. #import "FirebaseAppCheck/Sources/Public/FirebaseAppCheck/FIRAppCheckErrors.h"
  21. #import "FirebaseAppCheck/Sources/Public/FirebaseAppCheck/FIRAppCheckProvider.h"
  22. #import "FirebaseAppCheck/Sources/Public/FirebaseAppCheck/FIRAppCheckProviderFactory.h"
  23. #import "FirebaseAppCheck/Sources/Core/Errors/FIRAppCheckErrorUtil.h"
  24. #import "FirebaseAppCheck/Sources/Core/FIRAppCheckSettings.h"
  25. #import "FirebaseAppCheck/Sources/Core/FIRAppCheckToken+Internal.h"
  26. #import "FirebaseAppCheck/Sources/Core/FIRAppCheckTokenResult.h"
  27. #import "FirebaseCore/Extension/FirebaseCoreInternal.h"
  28. // The FAC token value returned when an error occurs.
  29. static NSString *const kDummyToken = @"eyJlcnJvciI6IlVOS05PV05fRVJST1IifQ==";
  30. extern void FIRResetLogger(void);
  31. @interface FIRAppCheck (Tests) <FIRAppCheckInterop, GACAppCheckTokenDelegate>
  32. - (instancetype)initWithAppName:(NSString *)appName
  33. appCheckCore:(GACAppCheck *)appCheckCore
  34. appCheckProvider:(id<FIRAppCheckProvider>)appCheckProvider
  35. notificationCenter:(NSNotificationCenter *)notificationCenter
  36. settings:(FIRAppCheckSettings *)settings;
  37. - (nullable instancetype)initWithApp:(FIRApp *)app;
  38. - (void)tokenDidUpdate:(nonnull GACAppCheckToken *)token
  39. serviceName:(nonnull NSString *)serviceName;
  40. @end
  41. @interface FIRAppCheckTests : XCTestCase
  42. @property(nonatomic) NSString *appName;
  43. @property(nonatomic) OCMockObject<FIRAppCheckProvider> *mockAppCheckProvider;
  44. @property(nonatomic) id mockSettings;
  45. @property(nonatomic) NSNotificationCenter *notificationCenter;
  46. @property(nonatomic) id mockAppCheckCore;
  47. @property(nonatomic) FIRAppCheck<FIRAppCheckInterop> *appCheck;
  48. @end
  49. @implementation FIRAppCheckTests
  50. - (void)setUp {
  51. [super setUp];
  52. FIRResetLogger();
  53. self.appName = @"FIRAppCheckTests";
  54. self.mockAppCheckProvider = OCMStrictProtocolMock(@protocol(FIRAppCheckProvider));
  55. self.mockSettings = OCMStrictClassMock([FIRAppCheckSettings class]);
  56. self.notificationCenter = [[NSNotificationCenter alloc] init];
  57. self.mockAppCheckCore = OCMStrictClassMock([GACAppCheck class]);
  58. self.appCheck = [[FIRAppCheck alloc] initWithAppName:self.appName
  59. appCheckCore:self.mockAppCheckCore
  60. appCheckProvider:self.mockAppCheckProvider
  61. notificationCenter:self.notificationCenter
  62. settings:self.mockSettings];
  63. }
  64. - (void)tearDown {
  65. self.appCheck = nil;
  66. self.mockAppCheckCore = nil;
  67. self.mockAppCheckProvider = nil;
  68. [super tearDown];
  69. }
  70. - (void)testInitWithApp {
  71. NSString *projectID = @"testInitWithApp_projectID";
  72. NSString *googleAppID = @"testInitWithApp_googleAppID";
  73. NSString *appName = @"testInitWithApp_appName";
  74. NSString *appGroupID = @"testInitWithApp_appGroupID";
  75. // 1. Stub FIRApp and validate usage.
  76. FIROptions *options = [[FIROptions alloc] initWithGoogleAppID:googleAppID GCMSenderID:@""];
  77. options.projectID = projectID;
  78. options.appGroupID = appGroupID;
  79. FIRApp *app = [[FIRApp alloc] initInstanceWithName:appName options:options];
  80. // The following disables automatic token refresh, which could interfere with tests.
  81. app.dataCollectionDefaultEnabled = NO;
  82. // 2. Stub attestation provider.
  83. OCMockObject<FIRAppCheckProviderFactory> *mockProviderFactory =
  84. OCMStrictProtocolMock(@protocol(FIRAppCheckProviderFactory));
  85. OCMockObject<FIRAppCheckProvider> *mockProvider =
  86. OCMStrictProtocolMock(@protocol(FIRAppCheckProvider));
  87. OCMExpect([mockProviderFactory createProviderWithApp:app]).andReturn(mockProvider);
  88. [FIRAppCheck setAppCheckProviderFactory:mockProviderFactory];
  89. // 3. Set the Firebase logging level to Debug.
  90. FIRSetLoggerLevel(FIRLoggerLevelDebug);
  91. // 4. Call init.
  92. FIRAppCheck *appCheck = [[FIRAppCheck alloc] initWithApp:app];
  93. XCTAssert([appCheck isKindOfClass:[FIRAppCheck class]]);
  94. // 5. Verify mocks.
  95. OCMVerifyAll(mockProviderFactory);
  96. OCMVerifyAll(mockProvider);
  97. // 6. Verify that the App Check Core logging level is also Debug.
  98. XCTAssertEqual(GACAppCheckLogger.logLevel, GACAppCheckLogLevelDebug);
  99. }
  100. - (void)testAppCheckInstanceForApp {
  101. FIROptions *options =
  102. [[FIROptions alloc] initWithGoogleAppID:@"1:100000000000:ios:aaaaaaaaaaaaaaaaaaaaaaaa"
  103. GCMSenderID:@"sender_id"];
  104. options.APIKey = @"api_key";
  105. options.projectID = @"project_id";
  106. FIRApp *app = [[FIRApp alloc] initInstanceWithName:@"testAppCheckInstanceForApp" options:options];
  107. // The following disables automatic token refresh, which could interfere with tests.
  108. app.dataCollectionDefaultEnabled = NO;
  109. XCTAssertNotNil(app);
  110. XCTAssertNotNil([FIRAppCheck appCheckWithApp:app]);
  111. // Verify that the App Check Core logging level is the default (Warning).
  112. XCTAssertEqual(GACAppCheckLogger.logLevel, GACAppCheckLogLevelWarning);
  113. }
  114. #pragma mark - Public Get Token
  115. - (void)testGetToken_Success {
  116. // 1. Create expected token and configure expectations.
  117. FIRAppCheckToken *expectedToken = [self validToken];
  118. NSArray * /*[tokenNotification, getToken]*/ expectations =
  119. [self configuredExpectations_TokenForcingRefresh_withExpectedToken:expectedToken];
  120. // 2. Request token and verify result.
  121. [self.appCheck
  122. tokenForcingRefresh:NO
  123. completion:^(FIRAppCheckToken *_Nullable token, NSError *_Nullable error) {
  124. [expectations.lastObject fulfill];
  125. XCTAssertNotNil(token);
  126. XCTAssertEqualObjects(token.token, expectedToken.token);
  127. XCTAssertNil(error);
  128. }];
  129. // 3. Wait for expectations and validate mocks.
  130. [self waitForExpectations:expectations timeout:0.5];
  131. [self verifyAllMocks];
  132. }
  133. - (void)testGetToken_AppCheckProviderError {
  134. // 1. Create expected token and error and configure expectations.
  135. FIRAppCheckToken *cachedToken = [self soonExpiringToken];
  136. NSError *providerError = [NSError errorWithDomain:@"FIRAppCheckTests" code:-1 userInfo:nil];
  137. NSArray * /*[tokenNotification, getToken]*/ expectations =
  138. [self configuredExpectations_GetTokenWhenError_withError:providerError andToken:cachedToken];
  139. // 2. Request token and verify result.
  140. [self.appCheck
  141. tokenForcingRefresh:NO
  142. completion:^(FIRAppCheckToken *_Nullable token, NSError *_Nullable error) {
  143. [expectations.lastObject fulfill];
  144. XCTAssertNil(token);
  145. XCTAssertNotNil(error);
  146. XCTAssertNotEqualObjects(error, providerError);
  147. XCTAssertEqualObjects(error.domain, FIRAppCheckErrorDomain);
  148. XCTAssertEqualObjects(error.userInfo[NSUnderlyingErrorKey], providerError);
  149. }];
  150. // 3. Wait for expectations and validate mocks.
  151. [self waitForExpectations:expectations timeout:0.5];
  152. [self verifyAllMocks];
  153. }
  154. - (void)testGetToken_ServerUnreachableError {
  155. // 1. Create expected error and configure expectations.
  156. NSError *serverError = [self appCheckCoreErrorWithCode:GACAppCheckErrorCodeServerUnreachable
  157. failureReason:@"API request error."
  158. underlyingError:[self internalError]];
  159. NSError *publicServerError = [FIRAppCheckErrorUtil publicDomainErrorWithError:serverError];
  160. NSArray * /*[tokenNotification, getToken]*/ expectations =
  161. [self configuredExpectations_GetTokenWhenError_withError:serverError andToken:nil];
  162. // 2. Request token and verify result.
  163. [self.appCheck
  164. tokenForcingRefresh:NO
  165. completion:^(FIRAppCheckToken *_Nullable token, NSError *_Nullable error) {
  166. [expectations.lastObject fulfill];
  167. XCTAssertNil(token);
  168. XCTAssertNotNil(error);
  169. XCTAssertEqualObjects(error, publicServerError);
  170. XCTAssertEqualObjects(error.domain, FIRAppCheckErrorDomain);
  171. XCTAssertEqual(error.code, FIRAppCheckErrorCodeServerUnreachable);
  172. XCTAssertEqualObjects(error.userInfo, serverError.userInfo);
  173. }];
  174. // 3. Wait for expectations and validate mocks.
  175. [self waitForExpectations:expectations timeout:0.5];
  176. [self verifyAllMocks];
  177. }
  178. - (void)testGetToken_UnsupportedError {
  179. // 1. Create expected error and configure expectations.
  180. NSError *providerError = [self appCheckCoreErrorWithCode:GACAppCheckErrorCodeUnsupported
  181. failureReason:@"AppAttestProvider unsupported"
  182. underlyingError:nil];
  183. NSError *publicProviderError = [FIRAppCheckErrorUtil publicDomainErrorWithError:providerError];
  184. NSArray * /*[tokenNotification, getToken]*/ expectations =
  185. [self configuredExpectations_GetTokenWhenError_withError:providerError andToken:nil];
  186. // 2. Request token and verify result.
  187. [self.appCheck
  188. tokenForcingRefresh:NO
  189. completion:^(FIRAppCheckToken *_Nullable token, NSError *_Nullable error) {
  190. [expectations.lastObject fulfill];
  191. XCTAssertNil(token);
  192. XCTAssertNotNil(error);
  193. XCTAssertEqualObjects(error, publicProviderError);
  194. XCTAssertEqualObjects(error.domain, FIRAppCheckErrorDomain);
  195. XCTAssertEqual(error.code, FIRAppCheckErrorCodeUnsupported);
  196. XCTAssertEqualObjects(error.userInfo, providerError.userInfo);
  197. }];
  198. // 3. Wait for expectations and validate mocks.
  199. [self waitForExpectations:expectations timeout:0.5];
  200. [self verifyAllMocks];
  201. }
  202. #pragma mark - FIRAppCheckInterop Get Token
  203. - (void)testInteropGetTokenForcingRefresh_Success {
  204. // 1. Create expected token and configure expectations.
  205. FIRAppCheckToken *expectedToken = [self validToken];
  206. NSArray * /*[tokenNotification, getToken]*/ expectations =
  207. [self configuredExpectations_TokenForcingRefresh_withExpectedToken:expectedToken];
  208. // 2. Request token and verify result.
  209. [self.appCheck getTokenForcingRefresh:NO
  210. completion:^(id<FIRAppCheckTokenResultInterop> tokenResult) {
  211. [expectations.lastObject fulfill];
  212. XCTAssertNotNil(tokenResult);
  213. XCTAssertEqualObjects(tokenResult.token, expectedToken.token);
  214. XCTAssertNil(tokenResult.error);
  215. }];
  216. // 3. Wait for expectations and validate mocks.
  217. [self waitForExpectations:expectations timeout:0.5];
  218. [self verifyAllMocks];
  219. }
  220. - (void)testInteropGetTokenForcingRefresh_AppCheckProviderError {
  221. // 1. Create expected tokens and errors and configure expectations.
  222. FIRAppCheckToken *cachedToken = [self soonExpiringToken];
  223. NSError *providerError = [NSError errorWithDomain:@"FIRAppCheckTests" code:-1 userInfo:nil];
  224. NSArray * /*[tokenNotification, getToken]*/ expectations =
  225. [self configuredExpectations_GetTokenWhenError_withError:providerError andToken:cachedToken];
  226. // 2. Request token and verify result.
  227. [self.appCheck
  228. getTokenForcingRefresh:NO
  229. completion:^(id<FIRAppCheckTokenResultInterop> result) {
  230. [expectations.lastObject fulfill];
  231. XCTAssertNotNil(result);
  232. XCTAssertEqualObjects(result.token, kDummyToken);
  233. XCTAssertEqualObjects(result.error, providerError);
  234. // Interop API does not wrap errors in public domain.
  235. XCTAssertNotEqualObjects(result.error.domain, FIRAppCheckErrorDomain);
  236. }];
  237. // 3. Wait for expectations and validate mocks.
  238. [self waitForExpectations:expectations timeout:0.5];
  239. [self verifyAllMocks];
  240. }
  241. - (void)testLimitedUseTokenWithSuccess {
  242. // 1. Expect token requested from app check provider.
  243. FIRAppCheckToken *expectedToken = [self validToken];
  244. GACAppCheckToken *expectedInternalToken = [expectedToken internalToken];
  245. GACAppCheckTokenResult *expectedTokenResult =
  246. [[GACAppCheckTokenResult alloc] initWithToken:expectedInternalToken];
  247. id completionArg = [OCMArg invokeBlockWithArgs:expectedTokenResult, nil];
  248. OCMStub([self.mockAppCheckCore limitedUseTokenWithCompletion:completionArg]);
  249. // 2. Don't expect token update notification to be sent.
  250. XCTestExpectation *notificationExpectation = [self tokenUpdateNotificationNotPosted];
  251. // 3. Expect token request to be completed.
  252. XCTestExpectation *getTokenExpectation = [self expectationWithDescription:@"getToken"];
  253. [self.appCheck
  254. limitedUseTokenWithCompletion:^(FIRAppCheckToken *_Nullable token, NSError *_Nullable error) {
  255. [getTokenExpectation fulfill];
  256. XCTAssertNotNil(token);
  257. XCTAssertEqualObjects(token.token, expectedToken.token);
  258. XCTAssertNil(error);
  259. }];
  260. [self waitForExpectations:@[ notificationExpectation, getTokenExpectation ] timeout:0.5];
  261. [self verifyAllMocks];
  262. }
  263. - (void)testLimitedUseToken_WhenTokenGenerationErrors {
  264. // 1. Expect error when requesting token from app check provider.
  265. NSError *providerError = [self appCheckCoreErrorWithCode:GACAppCheckErrorCodeKeychain
  266. failureReason:@"Keychain access error."
  267. underlyingError:[self internalError]];
  268. NSError *publicProviderError = [FIRAppCheckErrorUtil publicDomainErrorWithError:providerError];
  269. GACAppCheckTokenResult *expectedTokenResult =
  270. [[GACAppCheckTokenResult alloc] initWithError:providerError];
  271. id completionArg = [OCMArg invokeBlockWithArgs:expectedTokenResult, nil];
  272. OCMStub([self.mockAppCheckCore limitedUseTokenWithCompletion:completionArg]);
  273. // 2. Don't expect token requested from app check provider.
  274. OCMReject([self.mockAppCheckProvider getTokenWithCompletion:[OCMArg any]]);
  275. // 3. Don't expect token update notification to be sent.
  276. XCTestExpectation *notificationExpectation = [self tokenUpdateNotificationNotPosted];
  277. // 4. Expect token request to be completed.
  278. XCTestExpectation *getTokenExpectation = [self expectationWithDescription:@"getToken"];
  279. [self.appCheck
  280. limitedUseTokenWithCompletion:^(FIRAppCheckToken *_Nullable token, NSError *_Nullable error) {
  281. [getTokenExpectation fulfill];
  282. XCTAssertNotNil(error);
  283. XCTAssertNil(token.token);
  284. XCTAssertEqualObjects(error, publicProviderError);
  285. XCTAssertEqualObjects(error.domain, FIRAppCheckErrorDomain);
  286. XCTAssertEqual(error.code, FIRAppCheckErrorCodeKeychain);
  287. XCTAssertEqualObjects(error.userInfo, providerError.userInfo);
  288. }];
  289. [self waitForExpectations:@[ notificationExpectation, getTokenExpectation ] timeout:0.5];
  290. [self verifyAllMocks];
  291. }
  292. #pragma mark - Token update notifications
  293. - (void)testTokenUpdateNotificationKeys {
  294. XCTAssertEqualObjects([self.appCheck tokenDidChangeNotificationName],
  295. @"FIRAppCheckAppCheckTokenDidChangeNotification");
  296. XCTAssertEqualObjects([self.appCheck notificationAppNameKey],
  297. @"FIRAppCheckAppNameNotificationKey");
  298. XCTAssertEqualObjects([self.appCheck notificationTokenKey], @"FIRAppCheckTokenNotificationKey");
  299. }
  300. #pragma mark - Auto-refresh enabled
  301. - (void)testIsTokenAutoRefreshEnabled {
  302. // Expect value from settings to be used.
  303. [[[self.mockSettings expect] andReturnValue:@(NO)] isTokenAutoRefreshEnabled];
  304. XCTAssertFalse(self.appCheck.isTokenAutoRefreshEnabled);
  305. [[[self.mockSettings expect] andReturnValue:@(YES)] isTokenAutoRefreshEnabled];
  306. XCTAssertTrue(self.appCheck.isTokenAutoRefreshEnabled);
  307. OCMVerifyAll(self.mockSettings);
  308. }
  309. - (void)testSetIsTokenAutoRefreshEnabled {
  310. OCMExpect([self.mockSettings setIsTokenAutoRefreshEnabled:YES]);
  311. self.appCheck.isTokenAutoRefreshEnabled = YES;
  312. OCMExpect([self.mockSettings setIsTokenAutoRefreshEnabled:NO]);
  313. self.appCheck.isTokenAutoRefreshEnabled = NO;
  314. OCMVerifyAll(self.mockSettings);
  315. }
  316. #pragma mark - Helpers
  317. - (NSError *)internalError {
  318. return [NSError errorWithDomain:@"com.internal.error" code:-1 userInfo:nil];
  319. }
  320. - (NSError *)appCheckCoreErrorWithCode:(GACAppCheckErrorCode)code
  321. failureReason:(nullable NSString *)failureReason
  322. underlyingError:(nullable NSError *)underlyingError {
  323. NSMutableDictionary<NSErrorUserInfoKey, id> *userInfo = [NSMutableDictionary dictionary];
  324. userInfo[NSUnderlyingErrorKey] = underlyingError;
  325. userInfo[NSLocalizedFailureReasonErrorKey] = failureReason;
  326. return [NSError errorWithDomain:GACAppCheckErrorDomain code:code userInfo:userInfo];
  327. }
  328. - (FIRAppCheckToken *)validToken {
  329. return [[FIRAppCheckToken alloc] initWithToken:[NSUUID UUID].UUIDString
  330. expirationDate:[NSDate distantFuture]];
  331. }
  332. - (FIRAppCheckToken *)soonExpiringToken {
  333. NSDate *soonExpiringTokenDate = [NSDate dateWithTimeIntervalSinceNow:4.5 * 60];
  334. return [[FIRAppCheckToken alloc] initWithToken:@"valid" expirationDate:soonExpiringTokenDate];
  335. }
  336. - (XCTestExpectation *)tokenUpdateNotificationWithExpectedToken:(NSString *)expectedToken {
  337. XCTestExpectation *expectation =
  338. [self expectationForNotification:[self.appCheck tokenDidChangeNotificationName]
  339. object:nil
  340. notificationCenter:self.notificationCenter
  341. handler:^BOOL(NSNotification *_Nonnull notification) {
  342. XCTAssertEqualObjects(
  343. notification.userInfo[[self.appCheck notificationAppNameKey]],
  344. self.appName);
  345. XCTAssertEqualObjects(
  346. notification.userInfo[[self.appCheck notificationTokenKey]],
  347. expectedToken);
  348. XCTAssertEqualObjects(notification.object, self.appCheck);
  349. return YES;
  350. }];
  351. return expectation;
  352. }
  353. - (XCTestExpectation *)tokenUpdateNotificationNotPosted {
  354. XCTNSNotificationExpectation *expectation = [[XCTNSNotificationExpectation alloc]
  355. initWithName:[self.appCheck tokenDidChangeNotificationName]
  356. object:nil
  357. notificationCenter:self.notificationCenter];
  358. expectation.inverted = YES;
  359. return expectation;
  360. }
  361. - (NSArray<XCTestExpectation *> *)configuredExpectations_TokenForcingRefresh_withExpectedToken:
  362. (FIRAppCheckToken *)expectedToken {
  363. // 1. Expect token requested from app check core.
  364. GACAppCheckToken *expectedInternalToken = [expectedToken internalToken];
  365. GACAppCheckTokenResult *expectedTokenResult =
  366. [[GACAppCheckTokenResult alloc] initWithToken:expectedInternalToken];
  367. id completionArg = [OCMArg invokeBlockWithArgs:expectedTokenResult, nil];
  368. OCMExpect([self.mockAppCheckCore tokenForcingRefresh:NO completion:completionArg])
  369. .andDo(^(NSInvocation *invocation) {
  370. [self.appCheck tokenDidUpdate:expectedInternalToken serviceName:self.appName];
  371. })
  372. .ignoringNonObjectArgs();
  373. // 2. Expect token update notification to be sent.
  374. XCTestExpectation *tokenNotificationExpectation =
  375. [self tokenUpdateNotificationWithExpectedToken:expectedToken.token];
  376. // 3. Expect token request to be completed.
  377. XCTestExpectation *getTokenExpectation = [self expectationWithDescription:@"getToken"];
  378. return @[ tokenNotificationExpectation, getTokenExpectation ];
  379. }
  380. - (NSArray<XCTestExpectation *> *)
  381. configuredExpectations_GetTokenWhenError_withError:(NSError *_Nonnull)error
  382. andToken:(FIRAppCheckToken *_Nullable)token {
  383. // 1. Expect token requested from app check core.
  384. GACAppCheckTokenResult *expectedTokenResult =
  385. [[GACAppCheckTokenResult alloc] initWithError:error];
  386. id completionArg = [OCMArg invokeBlockWithArgs:expectedTokenResult, nil];
  387. OCMExpect([self.mockAppCheckCore tokenForcingRefresh:NO completion:completionArg])
  388. .ignoringNonObjectArgs();
  389. // 2. Don't expect token requested from app check provider.
  390. OCMReject([self.mockAppCheckProvider getTokenWithCompletion:[OCMArg any]]);
  391. // 3. Expect token update notification to be sent.
  392. XCTestExpectation *notificationExpectation = [self tokenUpdateNotificationNotPosted];
  393. // 4. Expect token request to be completed.
  394. XCTestExpectation *getTokenExpectation = [self expectationWithDescription:@"getToken"];
  395. return @[ notificationExpectation, getTokenExpectation ];
  396. }
  397. - (void)verifyAllMocks {
  398. OCMVerifyAll(self.mockAppCheckProvider);
  399. OCMVerifyAll(self.mockSettings);
  400. OCMVerifyAll(self.mockAppCheckCore);
  401. }
  402. @end