| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584 |
- /*
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #import <XCTest/XCTest.h>
- #import <OCMock/OCMock.h>
- #import "FBLPromise+Testing.h"
- #import <GoogleUtilities/GULURLSessionDataResponse.h>
- #import "FirebaseAppCheck/Sources/AppAttestProvider/API/FIRAppAttestAPIService.h"
- #import "FirebaseAppCheck/Sources/AppAttestProvider/API/FIRAppAttestAttestationResponse.h"
- #import "FirebaseAppCheck/Sources/Core/APIService/FIRAppCheckAPIService.h"
- #import "FirebaseAppCheck/Sources/Core/Errors/FIRAppCheckErrorUtil.h"
- #import "FirebaseAppCheck/Sources/Core/Errors/FIRAppCheckHTTPError.h"
- #import "FirebaseAppCheck/Sources/Core/FIRAppCheckToken+Internal.h"
- #import "FirebaseAppCheck/Sources/Public/FirebaseAppCheck/FIRAppCheckErrors.h"
- #import "FirebaseAppCheck/Tests/Unit/Utils/FIRFixtureLoader.h"
- #import "SharedTestUtilities/Date/FIRDateTestUtils.h"
- #import "SharedTestUtilities/URLSession/FIRURLSessionOCMockStub.h"
- @interface FIRAppAttestAPIServiceTests : XCTestCase
- @property(nonatomic) FIRAppAttestAPIService *appAttestAPIService;
- @property(nonatomic) id mockAPIService;
- @property(nonatomic) NSString *projectID;
- @property(nonatomic) NSString *appID;
- @end
- @implementation FIRAppAttestAPIServiceTests
- - (void)setUp {
- [super setUp];
- self.projectID = @"project_id";
- self.appID = @"app_id";
- self.mockAPIService = OCMProtocolMock(@protocol(FIRAppCheckAPIServiceProtocol));
- OCMStub([self.mockAPIService baseURL]).andReturn(@"https://test.appcheck.url.com/beta");
- self.appAttestAPIService = [[FIRAppAttestAPIService alloc] initWithAPIService:self.mockAPIService
- projectID:self.projectID
- appID:self.appID];
- }
- - (void)tearDown {
- [super tearDown];
- self.appAttestAPIService = nil;
- [self.mockAPIService stopMocking];
- self.mockAPIService = nil;
- }
- #pragma mark - Random challenge request
- - (void)testGetRandomChallengeWhenAPIResponseValid {
- // 1. Prepare API response.
- NSData *responseBody = [FIRFixtureLoader loadFixtureNamed:@"AppAttestResponseSuccess.json"];
- GULURLSessionDataResponse *validAPIResponse = [self APIResponseWithCode:200
- responseBody:responseBody];
- // 2. Stub API Service Request to return prepared API response.
- [self stubMockAPIServiceRequestForChallengeRequestWithResponse:validAPIResponse];
- // 3. Request the random challenge and verify results.
- __auto_type *promise = [self.appAttestAPIService getRandomChallenge];
- XCTAssert(FBLWaitForPromisesWithTimeout(1));
- XCTAssert(promise.isFulfilled);
- XCTAssertNotNil(promise.value);
- XCTAssertNil(promise.error);
- NSString *challengeString = [[NSString alloc] initWithData:promise.value
- encoding:NSUTF8StringEncoding];
- // The challenge stored in `AppAttestResponseSuccess.json` is a valid base64 encoding of
- // the string "random_challenge".
- XCTAssert([challengeString isEqualToString:@"random_challenge"]);
- OCMVerifyAll(self.mockAPIService);
- }
- - (void)testGetRandomChallengeWhenAPIError {
- // 1. Prepare API response.
- NSString *responseBodyString = @"Generate challenge failed with invalid format.";
- NSData *responseBody = [responseBodyString dataUsingEncoding:NSUTF8StringEncoding];
- GULURLSessionDataResponse *invalidAPIResponse = [self APIResponseWithCode:300
- responseBody:responseBody];
- FIRAppCheckHTTPError *APIError =
- [FIRAppCheckErrorUtil APIErrorWithHTTPResponse:invalidAPIResponse.HTTPResponse
- data:invalidAPIResponse.HTTPBody];
- // 2. Stub API Service Request to return prepared API response.
- [self stubMockAPIServiceRequestForChallengeRequestWithResponse:APIError];
- // 3. Request the random challenge and verify results.
- __auto_type *promise = [self.appAttestAPIService getRandomChallenge];
- XCTAssert(FBLWaitForPromisesWithTimeout(1));
- XCTAssert(promise.isRejected);
- XCTAssertNotNil(promise.error);
- XCTAssertNil(promise.value);
- // Assert error is as expected.
- XCTAssertEqualObjects(promise.error.domain, FIRAppCheckErrorDomain);
- XCTAssertEqual(promise.error.code, FIRAppCheckErrorCodeUnknown);
- // Expect response body and HTTP status code to be included in the error.
- NSString *failureReason = promise.error.userInfo[NSLocalizedFailureReasonErrorKey];
- XCTAssertTrue([failureReason containsString:@"300"]);
- XCTAssertTrue([failureReason containsString:responseBodyString]);
- OCMVerifyAll(self.mockAPIService);
- }
- - (void)testGetRandomChallengeWhenAPIResponseEmpty {
- // 1. Prepare API response.
- NSData *responseBody = [NSData data];
- GULURLSessionDataResponse *emptyAPIResponse = [self APIResponseWithCode:200
- responseBody:responseBody];
- // 2. Stub API Service Request to return prepared API response.
- [self stubMockAPIServiceRequestForChallengeRequestWithResponse:emptyAPIResponse];
- // 3. Request the random challenge and verify results.
- __auto_type *promise = [self.appAttestAPIService getRandomChallenge];
- XCTAssert(FBLWaitForPromisesWithTimeout(1));
- XCTAssert(promise.isRejected);
- XCTAssertNotNil(promise.error);
- XCTAssertNil(promise.value);
- // Expect response body and HTTP status code to be included in the error.
- NSString *failureReason = promise.error.userInfo[NSLocalizedFailureReasonErrorKey];
- XCTAssertEqualObjects(failureReason, @"Empty server response body.");
- OCMVerifyAll(self.mockAPIService);
- }
- - (void)testGetRandomChallengeWhenAPIResponseInvalidFormat {
- // 1. Prepare API response.
- NSString *responseBodyString = @"Generate challenge failed with invalid format.";
- NSData *responseBody = [responseBodyString dataUsingEncoding:NSUTF8StringEncoding];
- GULURLSessionDataResponse *validAPIResponse = [self APIResponseWithCode:200
- responseBody:responseBody];
- // 2. Stub API Service Request to return prepared API response.
- [self stubMockAPIServiceRequestForChallengeRequestWithResponse:validAPIResponse];
- // 3. Request the random challenge and verify results.
- __auto_type *promise = [self.appAttestAPIService getRandomChallenge];
- XCTAssert(FBLWaitForPromisesWithTimeout(1));
- XCTAssert(promise.isRejected);
- XCTAssertNotNil(promise.error);
- XCTAssertNil(promise.value);
- // Expect response body and HTTP status code to be included in the error.
- NSString *failureReason = promise.error.userInfo[NSLocalizedFailureReasonErrorKey];
- XCTAssertEqualObjects(failureReason, @"JSON serialization error.");
- OCMVerifyAll(self.mockAPIService);
- }
- - (void)testGetRandomChallengeWhenResponseMissingField {
- [self assertMissingFieldErrorWithFixture:@"AppAttestResponseMissingChallenge.json"
- missingField:@"challenge"];
- }
- - (void)assertMissingFieldErrorWithFixture:(NSString *)fixtureName
- missingField:(NSString *)fieldName {
- // 1. Prepare API response.
- NSData *missingFieldBody = [FIRFixtureLoader loadFixtureNamed:fixtureName];
- GULURLSessionDataResponse *incompleteAPIResponse = [self APIResponseWithCode:200
- responseBody:missingFieldBody];
- // 2. Stub API Service Request to return prepared API response.
- [self stubMockAPIServiceRequestForChallengeRequestWithResponse:incompleteAPIResponse];
- // 3. Request the random challenge and verify results.
- __auto_type *promise = [self.appAttestAPIService getRandomChallenge];
- XCTAssert(FBLWaitForPromisesWithTimeout(1));
- XCTAssert(promise.isRejected);
- XCTAssertNotNil(promise.error);
- XCTAssertNil(promise.value);
- // Assert error is as expected.
- XCTAssertEqualObjects(promise.error.domain, FIRAppCheckErrorDomain);
- XCTAssertEqual(promise.error.code, FIRAppCheckErrorCodeUnknown);
- // Expect missing field name to be included in the error.
- NSString *failureReason = promise.error.userInfo[NSLocalizedFailureReasonErrorKey];
- NSString *fieldNameString = [NSString stringWithFormat:@"`%@`", fieldName];
- XCTAssertTrue([failureReason containsString:fieldNameString],
- @"Fixture `%@`: expected missing field %@ error not found", fixtureName,
- fieldNameString);
- }
- #pragma mark - Assertion request
- - (void)testGetAppCheckTokenSuccess {
- NSData *artifact = [self generateRandomData];
- NSData *challenge = [self generateRandomData];
- NSData *assertion = [self generateRandomData];
- // 1. Prepare response.
- NSData *responseBody =
- [FIRFixtureLoader loadFixtureNamed:@"FACTokenExchangeResponseSuccess.json"];
- GULURLSessionDataResponse *validAPIResponse = [self APIResponseWithCode:200
- responseBody:responseBody];
- // 2. Stub API Service
- // 2.1. Return prepared response.
- [self expectTokenAPIRequestWithArtifact:artifact
- challenge:challenge
- assertion:assertion
- response:validAPIResponse
- error:nil];
- // 2.2. Return token from parsed response.
- FIRAppCheckToken *expectedToken = [[FIRAppCheckToken alloc] initWithToken:@"app_check_token"
- expirationDate:[NSDate date]
- receivedAtDate:[NSDate date]];
- [self expectTokenWithAPIReponse:validAPIResponse toReturnToken:expectedToken];
- // 3. Send request.
- __auto_type promise = [self.appAttestAPIService getAppCheckTokenWithArtifact:artifact
- challenge:challenge
- assertion:assertion];
- // 4. Verify.
- XCTAssert(FBLWaitForPromisesWithTimeout(1));
- XCTAssertTrue(promise.isFulfilled);
- XCTAssertNil(promise.error);
- XCTAssertEqualObjects(promise.value, expectedToken);
- XCTAssertEqualObjects(promise.value.token, expectedToken.token);
- XCTAssertEqualObjects(promise.value.expirationDate, expectedToken.expirationDate);
- XCTAssertEqualObjects(promise.value.receivedAtDate, expectedToken.receivedAtDate);
- OCMVerifyAll(self.mockAPIService);
- }
- - (void)testGetAppCheckTokenNetworkError {
- NSData *artifact = [self generateRandomData];
- NSData *challenge = [self generateRandomData];
- NSData *assertion = [self generateRandomData];
- // 1. Prepare response.
- NSData *responseBody =
- [FIRFixtureLoader loadFixtureNamed:@"FACTokenExchangeResponseSuccess.json"];
- GULURLSessionDataResponse *validAPIResponse = [self APIResponseWithCode:200
- responseBody:responseBody];
- // 2. Stub API Service
- // 2.1. Return prepared response.
- NSError *networkError = [NSError errorWithDomain:self.name code:0 userInfo:nil];
- [self expectTokenAPIRequestWithArtifact:artifact
- challenge:challenge
- assertion:assertion
- response:validAPIResponse
- error:networkError];
- // 3. Send request.
- __auto_type promise = [self.appAttestAPIService getAppCheckTokenWithArtifact:artifact
- challenge:challenge
- assertion:assertion];
- // 4. Verify.
- XCTAssert(FBLWaitForPromisesWithTimeout(1));
- XCTAssertTrue(promise.isRejected);
- XCTAssertNil(promise.value);
- XCTAssertEqualObjects(promise.error, networkError);
- OCMVerifyAll(self.mockAPIService);
- }
- - (void)testGetAppCheckTokenUnexpectedResponse {
- NSData *artifact = [self generateRandomData];
- NSData *challenge = [self generateRandomData];
- NSData *assertion = [self generateRandomData];
- // 1. Prepare response.
- NSData *responseBody =
- [FIRFixtureLoader loadFixtureNamed:@"DeviceCheckResponseMissingToken.json"];
- GULURLSessionDataResponse *validAPIResponse = [self APIResponseWithCode:200
- responseBody:responseBody];
- // 2. Stub API Service
- // 2.1. Return prepared response.
- [self expectTokenAPIRequestWithArtifact:artifact
- challenge:challenge
- assertion:assertion
- response:validAPIResponse
- error:nil];
- // 2.2. Return token from parsed response.
- [self expectTokenWithAPIReponse:validAPIResponse toReturnToken:nil];
- // 3. Send request.
- __auto_type promise = [self.appAttestAPIService getAppCheckTokenWithArtifact:artifact
- challenge:challenge
- assertion:assertion];
- // 4. Verify.
- XCTAssert(FBLWaitForPromisesWithTimeout(1));
- XCTAssertTrue(promise.isRejected);
- XCTAssertNil(promise.value);
- XCTAssertNotNil(promise.error);
- OCMVerifyAll(self.mockAPIService);
- }
- #pragma mark - Attestation request
- - (void)testAttestKeySuccess {
- NSData *attestation = [self generateRandomData];
- NSData *challenge = [self generateRandomData];
- NSString *keyID = [NSUUID UUID].UUIDString;
- // 1. Prepare response.
- NSData *responseBody =
- [FIRFixtureLoader loadFixtureNamed:@"AppAttestAttestationResponseSuccess.json"];
- GULURLSessionDataResponse *validAPIResponse = [self APIResponseWithCode:200
- responseBody:responseBody];
- // 2. Stub API Service
- // 2.1. Return prepared response.
- [self expectAttestAPIRequestWithAttestation:attestation
- keyID:keyID
- challenge:challenge
- response:validAPIResponse
- error:nil];
- // 3. Send request.
- __auto_type promise = [self.appAttestAPIService attestKeyWithAttestation:attestation
- keyID:keyID
- challenge:challenge];
- // 4. Verify.
- XCTAssert(FBLWaitForPromisesWithTimeout(1));
- XCTAssertTrue(promise.isFulfilled);
- XCTAssertNil(promise.error);
- NSData *expectedArtifact =
- [@"valid Firebase app attest artifact" dataUsingEncoding:NSUTF8StringEncoding];
- XCTAssertEqualObjects(promise.value.artifact, expectedArtifact);
- XCTAssertEqualObjects(promise.value.token.token, @"valid_app_check_token");
- XCTAssertTrue([FIRDateTestUtils isDate:promise.value.token.expirationDate
- approximatelyEqualCurrentPlusTimeInterval:1800
- precision:10]);
- OCMVerifyAll(self.mockAPIService);
- }
- - (void)testAttestKeyNetworkError {
- NSData *attestation = [self generateRandomData];
- NSData *challenge = [self generateRandomData];
- NSString *keyID = [NSUUID UUID].UUIDString;
- // 1. Stub API Service
- // 1.1. Return prepared response.
- NSError *networkError = [NSError errorWithDomain:self.name code:0 userInfo:nil];
- [self expectAttestAPIRequestWithAttestation:attestation
- keyID:keyID
- challenge:challenge
- response:nil
- error:networkError];
- // 2. Send request.
- __auto_type promise = [self.appAttestAPIService attestKeyWithAttestation:attestation
- keyID:keyID
- challenge:challenge];
- // 3. Verify.
- XCTAssert(FBLWaitForPromisesWithTimeout(1));
- XCTAssertTrue(promise.isRejected);
- XCTAssertNil(promise.value);
- XCTAssertEqualObjects(promise.error, networkError);
- OCMVerifyAll(self.mockAPIService);
- }
- - (void)testAttestKeyUnexpectedResponse {
- NSData *attestation = [self generateRandomData];
- NSData *challenge = [self generateRandomData];
- NSString *keyID = [NSUUID UUID].UUIDString;
- // 1. Prepare unexpected response.
- NSData *responseBody =
- [FIRFixtureLoader loadFixtureNamed:@"FACTokenExchangeResponseSuccess.json"];
- GULURLSessionDataResponse *validAPIResponse = [self APIResponseWithCode:200
- responseBody:responseBody];
- // 2. Stub API Service
- // 2.1. Return prepared response.
- [self expectAttestAPIRequestWithAttestation:attestation
- keyID:keyID
- challenge:challenge
- response:validAPIResponse
- error:nil];
- // 3. Send request.
- __auto_type promise = [self.appAttestAPIService attestKeyWithAttestation:attestation
- keyID:keyID
- challenge:challenge];
- // 4. Verify.
- XCTAssert(FBLWaitForPromisesWithTimeout(1));
- XCTAssertTrue(promise.isRejected);
- XCTAssertNil(promise.value);
- XCTAssertNotNil(promise.error);
- OCMVerifyAll(self.mockAPIService);
- }
- #pragma mark - Helpers
- - (GULURLSessionDataResponse *)APIResponseWithCode:(NSInteger)code
- responseBody:(NSData *)responseBody {
- XCTAssertNotNil(responseBody);
- NSHTTPURLResponse *HTTPResponse = [FIRURLSessionOCMockStub HTTPResponseWithCode:code];
- GULURLSessionDataResponse *APIResponse =
- [[GULURLSessionDataResponse alloc] initWithResponse:HTTPResponse HTTPBody:responseBody];
- return APIResponse;
- }
- - (void)stubMockAPIServiceRequestForChallengeRequestWithResponse:(id)response {
- id URLValidationArg = [self URLValidationArgumentWithResource:@"generateAppAttestChallenge"];
- OCMStub([self.mockAPIService sendRequestWithURL:URLValidationArg
- HTTPMethod:@"POST"
- body:nil
- additionalHeaders:nil])
- .andDo(^(NSInvocation *invocation) {
- XCTAssertFalse([NSThread isMainThread]);
- })
- .andReturn([FBLPromise resolvedWith:response]);
- }
- - (id)URLValidationArgumentWithResource:(NSString *)resource {
- NSString *expectedRequestURL =
- [NSString stringWithFormat:@"%@/projects/%@/apps/%@:%@", [self.mockAPIService baseURL],
- self.projectID, self.appID, resource];
- id URLValidationArg = [OCMArg checkWithBlock:^BOOL(NSURL *URL) {
- XCTAssertEqualObjects(URL.absoluteString, expectedRequestURL);
- return YES;
- }];
- return URLValidationArg;
- }
- - (void)expectTokenAPIRequestWithArtifact:(NSData *)attestation
- challenge:(NSData *)challenge
- assertion:(NSData *)assertion
- response:(nullable GULURLSessionDataResponse *)response
- error:(nullable NSError *)error {
- id URLValidationArg = [self URLValidationArgumentWithResource:@"exchangeAppAttestAssertion"];
- id bodyValidationArg = [OCMArg checkWithBlock:^BOOL(NSData *requestBody) {
- NSDictionary<NSString *, id> *decodedData = [NSJSONSerialization JSONObjectWithData:requestBody
- options:0
- error:nil];
- XCTAssert([decodedData isKindOfClass:[NSDictionary class]]);
- // Validate artifact field.
- NSString *base64EncodedArtifact = decodedData[@"artifact"];
- XCTAssert([base64EncodedArtifact isKindOfClass:[NSString class]]);
- NSData *decodedAttestation = [[NSData alloc] initWithBase64EncodedString:base64EncodedArtifact
- options:0];
- XCTAssertEqualObjects(decodedAttestation, attestation);
- // Validate challenge field.
- NSString *base64EncodedChallenge = decodedData[@"challenge"];
- XCTAssert([base64EncodedChallenge isKindOfClass:[NSString class]]);
- NSData *decodedChallenge = [[NSData alloc] initWithBase64EncodedString:base64EncodedChallenge
- options:0];
- XCTAssertEqualObjects(decodedChallenge, challenge);
- // Validate assertion field.
- NSString *base64EncodedAssertion = decodedData[@"assertion"];
- XCTAssert([base64EncodedAssertion isKindOfClass:[NSString class]]);
- NSData *decodedAssertion = [[NSData alloc] initWithBase64EncodedString:base64EncodedAssertion
- options:0];
- XCTAssertEqualObjects(decodedAssertion, assertion);
- return YES;
- }];
- FBLPromise *responsePromise = [FBLPromise pendingPromise];
- if (error) {
- [responsePromise reject:error];
- } else {
- [responsePromise fulfill:response];
- }
- OCMExpect([self.mockAPIService sendRequestWithURL:URLValidationArg
- HTTPMethod:@"POST"
- body:bodyValidationArg
- additionalHeaders:@{@"Content-Type" : @"application/json"}])
- .andReturn(responsePromise);
- }
- - (void)expectTokenWithAPIReponse:(nonnull GULURLSessionDataResponse *)response
- toReturnToken:(nullable FIRAppCheckToken *)token {
- FBLPromise *tokenPromise = [FBLPromise pendingPromise];
- if (token) {
- [tokenPromise fulfill:token];
- } else {
- NSError *tokenError = [NSError errorWithDomain:self.name code:0 userInfo:nil];
- [tokenPromise reject:tokenError];
- }
- OCMExpect([self.mockAPIService appCheckTokenWithAPIResponse:response]).andReturn(tokenPromise);
- }
- - (void)expectAttestAPIRequestWithAttestation:(NSData *)attestation
- keyID:(NSString *)keyID
- challenge:(NSData *)challenge
- response:(nullable GULURLSessionDataResponse *)response
- error:(nullable NSError *)error {
- id URLValidationArg = [self URLValidationArgumentWithResource:@"exchangeAppAttestAttestation"];
- id bodyValidationArg = [OCMArg checkWithBlock:^BOOL(NSData *requestBody) {
- NSDictionary<NSString *, id> *decodedData = [NSJSONSerialization JSONObjectWithData:requestBody
- options:0
- error:nil];
- XCTAssert([decodedData isKindOfClass:[NSDictionary class]]);
- // Validate attestation field.
- NSString *base64EncodedAttestation = decodedData[@"attestation_statement"];
- XCTAssert([base64EncodedAttestation isKindOfClass:[NSString class]]);
- NSData *decodedAttestation =
- [[NSData alloc] initWithBase64EncodedString:base64EncodedAttestation options:0];
- XCTAssertEqualObjects(decodedAttestation, attestation);
- // Validate challenge field.
- NSString *base64EncodedChallenge = decodedData[@"challenge"];
- XCTAssert([base64EncodedAttestation isKindOfClass:[NSString class]]);
- NSData *decodedChallenge = [[NSData alloc] initWithBase64EncodedString:base64EncodedChallenge
- options:0];
- XCTAssertEqualObjects(decodedChallenge, challenge);
- // Validate key ID field.
- NSString *keyIDField = decodedData[@"key_id"];
- XCTAssert([base64EncodedAttestation isKindOfClass:[NSString class]]);
- XCTAssertEqualObjects(keyIDField, keyID);
- return YES;
- }];
- FBLPromise *resultPromise = [FBLPromise pendingPromise];
- if (error) {
- [resultPromise reject:error];
- } else {
- [resultPromise fulfill:response];
- }
- OCMExpect([self.mockAPIService sendRequestWithURL:URLValidationArg
- HTTPMethod:@"POST"
- body:bodyValidationArg
- additionalHeaders:@{@"Content-Type" : @"application/json"}])
- .andReturn(resultPromise);
- }
- - (NSData *)generateRandomData {
- return [[NSUUID UUID].UUIDString dataUsingEncoding:NSUTF8StringEncoding];
- }
- @end
|