Authored by 周蓉君

重构NetworkService,提供封装好的网络服务接口。修改相关测试用例。Review by 阿瑟。

... ... @@ -15,9 +15,9 @@
194EDC841A7F52D100421E6C /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 194EDC821A7F52D100421E6C /* LaunchScreen.xib */; };
194EDC901A7F52D100421E6C /* YH_AnalyticsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 194EDC8F1A7F52D100421E6C /* YH_AnalyticsTests.m */; };
194EDC9C1A7F555800421E6C /* YH_Analytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 194EDC9B1A7F555800421E6C /* YH_Analytics.m */; };
CA5FDA2A1AEE302F00F86398 /* YHNetworkService.m in Sources */ = {isa = PBXBuildFile; fileRef = CA5FDA291AEE302F00F86398 /* YHNetworkService.m */; };
CA7AC7831ADE06F300F30791 /* YHCrashReporterTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CA7AC7821ADE06F300F30791 /* YHCrashReporterTests.m */; };
CA7AC7851ADE073200F30791 /* NSString+YHAnalyticsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CA7AC7841ADE073200F30791 /* NSString+YHAnalyticsTests.m */; };
CA7AC7871ADE075E00F30791 /* YHNetworkAssistantTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CA7AC7861ADE075E00F30791 /* YHNetworkAssistantTests.m */; };
CA7AC7891ADE078200F30791 /* YHAssemblyAssistantTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CA7AC7881ADE078200F30791 /* YHAssemblyAssistantTests.m */; };
CA7AC78B1ADE079800F30791 /* YHNetworkUserAgentTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CA7AC78A1ADE079800F30791 /* YHNetworkUserAgentTests.m */; };
CA7AC78F1ADE08CA00F30791 /* YHDeviceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CA7AC78E1ADE08CA00F30791 /* YHDeviceTests.m */; };
... ... @@ -31,6 +31,7 @@
CA7AC7A01ADE0C4F00F30791 /* YHEventFactoryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CA7AC79F1ADE0C4F00F30791 /* YHEventFactoryTests.m */; };
CA7AC7A21ADE0C6600F30791 /* YHStatusFactoryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CA7AC7A11ADE0C6600F30791 /* YHStatusFactoryTests.m */; };
CA7AC7A41ADF9FCB00F30791 /* YH_AnalyticsLogicTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CA7AC7A31ADF9FCB00F30791 /* YH_AnalyticsLogicTests.m */; };
CA873DAA1AEF51AE008095A4 /* YHNetworkServiceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CA873DA91AEF51AE008095A4 /* YHNetworkServiceTests.m */; };
CAA6BD371AE4E857006C3332 /* FakeLocationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = CAA6BD361AE4E857006C3332 /* FakeLocationManager.m */; };
CAA6BD3E1AE79ECC006C3332 /* YHAssemblyAssistantLogicTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CAA6BD3D1AE79ECC006C3332 /* YHAssemblyAssistantLogicTests.m */; };
CABC32831AD7CEB8002A4260 /* libOCMock.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CABC32821AD7CEB8002A4260 /* libOCMock.a */; };
... ... @@ -63,7 +64,6 @@
E7ADAE551AB94EBD00C9DD0B /* YHEventFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = E7ADAE541AB94EBD00C9DD0B /* YHEventFactory.m */; };
E7ADAE581AB94ED400C9DD0B /* YHStatusFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = E7ADAE571AB94ED400C9DD0B /* YHStatusFactory.m */; };
E7ADAE5B1AB95BC800C9DD0B /* YHAssemblyAssistant.m in Sources */ = {isa = PBXBuildFile; fileRef = E7ADAE5A1AB95BC800C9DD0B /* YHAssemblyAssistant.m */; };
E7ADAE5E1AB95D2800C9DD0B /* YHNetworkAssistant.m in Sources */ = {isa = PBXBuildFile; fileRef = E7ADAE5D1AB95D2800C9DD0B /* YHNetworkAssistant.m */; };
E7B8DE221A81D68600102CC4 /* NSString+YHAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = E7B8DE211A81D68600102CC4 /* NSString+YHAnalytics.m */; };
E7B8DE421A81DCBD00102CC4 /* Reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = E7B8DE3A1A81DCBD00102CC4 /* Reachability.m */; };
E7B8DE461A81ED8F00102CC4 /* YHNetworkUserAgent.m in Sources */ = {isa = PBXBuildFile; fileRef = E7B8DE451A81ED8F00102CC4 /* YHNetworkUserAgent.m */; };
... ... @@ -114,9 +114,10 @@
194EDC8F1A7F52D100421E6C /* YH_AnalyticsTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = YH_AnalyticsTests.m; sourceTree = "<group>"; };
194EDC9A1A7F555800421E6C /* YH_Analytics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YH_Analytics.h; sourceTree = "<group>"; };
194EDC9B1A7F555800421E6C /* YH_Analytics.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YH_Analytics.m; sourceTree = "<group>"; };
CA5FDA281AEE302F00F86398 /* YHNetworkService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YHNetworkService.h; sourceTree = "<group>"; };
CA5FDA291AEE302F00F86398 /* YHNetworkService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YHNetworkService.m; sourceTree = "<group>"; };
CA7AC7821ADE06F300F30791 /* YHCrashReporterTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YHCrashReporterTests.m; sourceTree = "<group>"; };
CA7AC7841ADE073200F30791 /* NSString+YHAnalyticsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+YHAnalyticsTests.m"; sourceTree = "<group>"; };
CA7AC7861ADE075E00F30791 /* YHNetworkAssistantTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YHNetworkAssistantTests.m; sourceTree = "<group>"; };
CA7AC7881ADE078200F30791 /* YHAssemblyAssistantTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YHAssemblyAssistantTests.m; sourceTree = "<group>"; };
CA7AC78A1ADE079800F30791 /* YHNetworkUserAgentTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YHNetworkUserAgentTests.m; sourceTree = "<group>"; };
CA7AC78E1ADE08CA00F30791 /* YHDeviceTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YHDeviceTests.m; sourceTree = "<group>"; };
... ... @@ -130,6 +131,7 @@
CA7AC79F1ADE0C4F00F30791 /* YHEventFactoryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YHEventFactoryTests.m; sourceTree = "<group>"; };
CA7AC7A11ADE0C6600F30791 /* YHStatusFactoryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YHStatusFactoryTests.m; sourceTree = "<group>"; };
CA7AC7A31ADF9FCB00F30791 /* YH_AnalyticsLogicTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YH_AnalyticsLogicTests.m; sourceTree = "<group>"; };
CA873DA91AEF51AE008095A4 /* YHNetworkServiceTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YHNetworkServiceTests.m; sourceTree = "<group>"; };
CAA6BD351AE4E857006C3332 /* FakeLocationManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FakeLocationManager.h; sourceTree = "<group>"; };
CAA6BD361AE4E857006C3332 /* FakeLocationManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FakeLocationManager.m; sourceTree = "<group>"; };
CAA6BD3D1AE79ECC006C3332 /* YHAssemblyAssistantLogicTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YHAssemblyAssistantLogicTests.m; sourceTree = "<group>"; };
... ... @@ -203,8 +205,6 @@
E7ADAE571AB94ED400C9DD0B /* YHStatusFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YHStatusFactory.m; sourceTree = "<group>"; };
E7ADAE591AB95BC800C9DD0B /* YHAssemblyAssistant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YHAssemblyAssistant.h; sourceTree = "<group>"; };
E7ADAE5A1AB95BC800C9DD0B /* YHAssemblyAssistant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YHAssemblyAssistant.m; sourceTree = "<group>"; };
E7ADAE5C1AB95D2800C9DD0B /* YHNetworkAssistant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YHNetworkAssistant.h; sourceTree = "<group>"; };
E7ADAE5D1AB95D2800C9DD0B /* YHNetworkAssistant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YHNetworkAssistant.m; sourceTree = "<group>"; };
E7B8DE201A81D68600102CC4 /* NSString+YHAnalytics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+YHAnalytics.h"; sourceTree = "<group>"; };
E7B8DE211A81D68600102CC4 /* NSString+YHAnalytics.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+YHAnalytics.m"; sourceTree = "<group>"; };
E7B8DE391A81DCBD00102CC4 /* Reachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Reachability.h; sourceTree = "<group>"; };
... ... @@ -335,10 +335,10 @@
CA7AC78C1ADE088D00F30791 /* UtilsTest */ = {
isa = PBXGroup;
children = (
CA7AC7861ADE075E00F30791 /* YHNetworkAssistantTests.m */,
CA7AC7881ADE078200F30791 /* YHAssemblyAssistantTests.m */,
CA7AC78A1ADE079800F30791 /* YHNetworkUserAgentTests.m */,
CAA6BD3D1AE79ECC006C3332 /* YHAssemblyAssistantLogicTests.m */,
CA873DA91AEF51AE008095A4 /* YHNetworkServiceTests.m */,
);
name = UtilsTest;
sourceTree = "<group>";
... ... @@ -512,8 +512,8 @@
E7B8DE451A81ED8F00102CC4 /* YHNetworkUserAgent.m */,
E7ADAE591AB95BC800C9DD0B /* YHAssemblyAssistant.h */,
E7ADAE5A1AB95BC800C9DD0B /* YHAssemblyAssistant.m */,
E7ADAE5C1AB95D2800C9DD0B /* YHNetworkAssistant.h */,
E7ADAE5D1AB95D2800C9DD0B /* YHNetworkAssistant.m */,
CA5FDA281AEE302F00F86398 /* YHNetworkService.h */,
CA5FDA291AEE302F00F86398 /* YHNetworkService.m */,
);
path = Utils;
sourceTree = "<group>";
... ... @@ -651,7 +651,6 @@
buildActionMask = 2147483647;
files = (
E74D45B71ABA7C6300EFE12E /* AFURLConnectionOperation.m in Sources */,
E7ADAE5E1AB95D2800C9DD0B /* YHNetworkAssistant.m in Sources */,
194EDC7C1A7F52D100421E6C /* ViewController.m in Sources */,
E74D45BC1ABA7C6300EFE12E /* UIActivityIndicatorView+AFNetworking.m in Sources */,
E74D45B21ABA7C6300EFE12E /* AFHTTPRequestOperation.m in Sources */,
... ... @@ -667,6 +666,7 @@
E7ADAE431AB9479600C9DD0B /* YHDataFactory.m in Sources */,
E74D45B61ABA7C6300EFE12E /* AFSecurityPolicy.m in Sources */,
E74D45BA1ABA7C6300EFE12E /* AFURLSessionManager.m in Sources */,
CA5FDA2A1AEE302F00F86398 /* YHNetworkService.m in Sources */,
E7ADAE3E1AB946C100C9DD0B /* YHStatus.m in Sources */,
E74D45BE1ABA7C6300EFE12E /* UIButton+AFNetworking.m in Sources */,
194EDC791A7F52D100421E6C /* AppDelegate.m in Sources */,
... ... @@ -696,13 +696,13 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
CA7AC7871ADE075E00F30791 /* YHNetworkAssistantTests.m in Sources */,
CA7AC7A21ADE0C6600F30791 /* YHStatusFactoryTests.m in Sources */,
CAA6BD3E1AE79ECC006C3332 /* YHAssemblyAssistantLogicTests.m in Sources */,
194EDC901A7F52D100421E6C /* YH_AnalyticsTests.m in Sources */,
CA7AC7951ADE090800F30791 /* YHStatusTests.m in Sources */,
CA7AC78B1ADE079800F30791 /* YHNetworkUserAgentTests.m in Sources */,
CA7AC7831ADE06F300F30791 /* YHCrashReporterTests.m in Sources */,
CA873DAA1AEF51AE008095A4 /* YHNetworkServiceTests.m in Sources */,
CA7AC78F1ADE08CA00F30791 /* YHDeviceTests.m in Sources */,
CA7AC7891ADE078200F30791 /* YHAssemblyAssistantTests.m in Sources */,
CA7AC7931ADE08F000F30791 /* YHEventTests.m in Sources */,
... ...
... ... @@ -14,7 +14,6 @@
#include <sys/socket.h>
#import <UIKit/UIKit.h>
#import <AdSupport/AdSupport.h>
//#import "YHNetworkUserAgent.h"
#import "OpenUDID.h"
#import "YHDevice.h"
... ...
... ... @@ -7,8 +7,6 @@
//
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#import "YHNetworkAssistant.h"
#import "YHAnalyItemData.h"
... ... @@ -31,7 +29,7 @@ extern NSString * const JsonKeyDataTypeErrors;
用于组装数据
*/
@interface YHAssemblyAssistant : NSObject <CLLocationManagerDelegate>
@interface YHAssemblyAssistant : NSObject
+ (instancetype)sharedInstance;
... ...
... ... @@ -6,9 +6,10 @@
// Copyright (c) 2015年 YOHO. All rights reserved.
//
#import <CoreLocation/CoreLocation.h>
#import <CoreTelephony/CTCarrier.h>
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
#import "Reachability.h"
#import "YHNetworkService.h"
#import "YHAssemblyAssistant.h"
//#import "YHErrorFactory.h"
//#import "YHEventFactory.h"
... ... @@ -20,6 +21,7 @@
#import "YHDevice.h"
#import "YHStatus.h"
#define kPathCaches [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0]
#define kPathLogSystem [kPathCaches stringByAppendingPathComponent:@"YHLogSystem"]
#define kYASApiMethod @"yas_mobile"
... ... @@ -46,7 +48,7 @@ static dispatch_queue_t persisting_queue() {
return persisting_queue;
}
@interface YHAssemblyAssistant ()
@interface YHAssemblyAssistant () <CLLocationManagerDelegate>
/**
* 定位服务
... ... @@ -285,10 +287,12 @@ static dispatch_queue_t persisting_queue() {
if (event) {
[self.immediUploadItemDic setObject:[[NSMutableArray alloc]initWithObjects:event.jsonDictionary, nil] forKey:JsonKeyDataTypeEvents];
[[YHNetworkAssistant sharedInstance] postWithAPI:kYASApiMethod parameters:self.immediUploadItemDic from:self success:^(id responseObject) {
} failure:^(NSError *error) {
NSLog(@"error = %@", error.localizedDescription);
[[YHNetworkService sharedInstance] uploadLogData:self.immediUploadItemDic completionBlock:^(BOOL success, NSError *error) {
if (success) {
NSLog(@"upload immedialite data success.");
} else {
NSLog(@"error = %@", error.localizedDescription);
}
}];
}
} else if(itemData.dataType == YHItemDataTypeError) {
... ... @@ -296,10 +300,12 @@ static dispatch_queue_t persisting_queue() {
if (error) {
[self.immediUploadItemDic setObject:[[NSMutableArray alloc]initWithObjects:error.jsonDictionary, nil] forKey:JsonKeyDataTypeErrors];
[[YHNetworkAssistant sharedInstance] postWithAPI:kYASApiMethod parameters:self.immediUploadItemDic from:self success:^(id responseObject) {
} failure:^(NSError *error) {
NSLog(@"error = %@", error.localizedDescription);
[[YHNetworkService sharedInstance] uploadLogData:self.immediUploadItemDic completionBlock:^(BOOL success, NSError *error) {
if (success) {
NSLog(@"upload immedialite data success.");
} else {
NSLog(@"error = %@", error.localizedDescription);
}
}];
}
} else {
... ... @@ -317,11 +323,14 @@ static dispatch_queue_t persisting_queue() {
if (uploadData) {
[[YHNetworkAssistant sharedInstance] postWithAPI:kYASApiMethod parameters:uploadData from:self success:^(id responseObject) {
[self removeLocalFile];
} failure:^(NSError *error) {
NSLog(@"error = %@", error.localizedDescription);
[[YHNetworkService sharedInstance] uploadLogData:uploadData completionBlock:^(BOOL success, NSError *error) {
if (success) {
NSLog(@"upload immedialite data success.");
// 删除已发送的本地文件
[self removeLocalFile];
} else {
NSLog(@"error = %@", error.localizedDescription);
}
}];
}
}
... ... @@ -344,11 +353,12 @@ static dispatch_queue_t persisting_queue() {
CTRadioAccessTechnologyeHRPD - 3G (or 3.5 - eHRPD is to allow migration from CDMA EVDO to LTE)
CTRadioAccessTechnologyLTE - 4G (allowed to be called 4G by the ITU as mentioend above)
*/
[[YHNetworkAssistant sharedInstance] addReachabilityChangedHandler:^(AFNetworkReachabilityStatus networkStatus) {
[[YHNetworkService sharedInstance] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
NSString *net = kNetWorkStatusUnknow;
CTTelephonyNetworkInfo *netInfo = [[CTTelephonyNetworkInfo alloc] init];
switch (networkStatus) {
switch (status) {
case AFNetworkReachabilityStatusUnknown:
case AFNetworkReachabilityStatusNotReachable:
net = kNetWorkStatusUnknow;
... ... @@ -382,6 +392,7 @@ static dispatch_queue_t persisting_queue() {
if ([self updateNetWorkStatus:net]) {
[self updateImmediUploadDic];
}
}];
}
... ...
... ... @@ -125,17 +125,21 @@ void uncaughtCrashExceptionHandler(NSException *exception)
- (void)handleSignal:(NSDictionary*)userInfo
{
NSLog(@"crash============:\n%@", userInfo);
if (userInfo) {
[[YH_Analytics sharedInstance] logError:@"CRASH" parameters:@{ JsonKeyErrorST: userInfo}];
if (!userInfo || ![userInfo isKindOfClass:[NSDictionary class]]) {
return;
}
[[YH_Analytics sharedInstance] logError:@"CRASH" parameters:@{ JsonKeyErrorST: userInfo}];
}
- (void)handleNSException:(NSDictionary*)userInfo
{
NSLog(@"crash============:\n%@", userInfo);
if (userInfo) {
[[YH_Analytics sharedInstance] logError:@"CRASH" parameters:@{ JsonKeyErrorST: userInfo}];
if (!userInfo || ![userInfo isKindOfClass:[NSDictionary class]]) {
return;
}
[[YH_Analytics sharedInstance] logError:@"CRASH" parameters:@{ JsonKeyErrorST: userInfo}];
}
@end
... ...
//
// YHNetworkAssistant.h
// YH_Analytics
//
// Created by Arthur on 15/3/18.
// Copyright (c) 2015年 YOHO. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "AFNetworking.h"
#define kSafeValue(X) (!(X) ? [NSNull null] : (X))
static NSString * const YHEAPIErrorDomain = @"YHEAPIErrorDomain";
/**
* Responsible for the task of handling networks
*/
@interface YHNetworkAssistant : NSObject
#pragma mark - Init
+ (instancetype)sharedInstance;
/**
* Initializes your network engine with a hostname
*
* @param hostName The host name
*
* @return
*/
- (instancetype)initWithHostName:(NSString *)hostName;
/**
* Initializes your network engine with a hostname and custom header fields
*
* @param hostName The host name
* @param headers HTTP Header
*
* @return
*/
- (id)initWithHostName:(NSString *)hostName customHeaderFields:(NSDictionary *)headers;
/**
* Initializes your network engine with a hostname, api path and custom header fields
*
* @param hostName The host name
* @param apiPath You can use this method if your server's API location is not at the root (/)
* @param headers HTTP Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
*
* @return
*/
- (id)initWithHostName:(NSString *)hostName apiPath:(NSString *)apiPath customHeaderFields:(NSDictionary *)headers;
#pragma mark - Operation
/**
* Enqueues your operation into the shared queue
*
* @param requestOperation A requestOperation that will be add to the queue
*/
- (void)enqueueOperation:(AFHTTPRequestOperation *)requestOperation;
/**
* Remove your operation out of the shared queue
*
* @param aAperation A requestOperation that will be remove from the queue
*/
+ (void)removeOperation:(AFHTTPRequestOperation *)aAperation;
/**
* Cancel your operation
*
* @param requester
*/
+ (void)cancelOperationsFrom:(id)requester;
/**
* using the `GET`
*
* @param api The api string used to create the request URL string
* @param parameters The parameters to be encoded according to the client request serializer.
* @param requester
* @param success A block object to be executed when the request operation finishes successfully
* @param failure A block object to be executed when the request operation finishes unsuccessfully
*/
- (void)getWithAPI:(NSString *)api parameters:(NSDictionary *)parameters from:(id)requester success:(void(^)(id responseObject))success failure:(void(^)(NSError *error))failure;
/**
* using the `POST`
*
* @param api The api string used to create the request URL string
* @param parameters The parameters to be encoded according to the client request serializer.
* @param requester requester
* @param success A block object to be executed when the request operation finishes successfully
* @param failure A block object to be executed when the request operation finishes unsuccessfully
*/
- (void)postWithAPI:(NSString *)api parameters:(NSDictionary *)parameters from:(id)requester success:(void(^)(id responseObject))success failure:(void(^)(NSError *error))failure;
/**
* using the `POST`
*
* @param api The api string used to create the request URL string
* @param parameters The parameters to be encoded according to the client request serializer.
* @param files Post files
* @param requester requester
* @param success A block object to be executed when the request operation finishes successfully
* @param failure A block object to be executed when the request operation finishes unsuccessfully
*/
- (void)postWithAPI:(NSString *)api parameters:(NSDictionary *)parameters files:(NSDictionary *)files from:(id)requester success:(void(^)(id responseObject))success failure:(void(^)(NSError *error))failure;
#pragma mark - Network Reachability
/**
* Checks current reachable status
* This method is a handy helper that you can use to check for network reachability.
*/
- (BOOL)isReachable;
/**
* Check that the network status for wifi
*
* @return
*/
- (BOOL)isReachableWifi;
/**
* The current network reachability status.
*
* @param reachabilityChangedHandler A block object to be executed when the network availability was changed
*/
- (void)addReachabilityChangedHandler:(void (^)(AFNetworkReachabilityStatus networkStatus))reachabilityChangedHandler;
@end
//
// YHNetworkAssistant.m
// YH_Analytics
//
// Created by Arthur on 15/3/18.
// Copyright (c) 2015年 YOHO. All rights reserved.
//
#import "YHNetworkAssistant.h"
#import "NSString+YHAnalytics.h"
//#define IS_TEST 0
#define kAnalizedURL @"http://analytics.yhurl.com/"
static NSMutableSet *_allOperations;
NSMutableArray *_reachabilityChangedHandlers;
AFNetworkReachabilityStatus _currentNetworkStatus;
static dispatch_queue_t network_assistant_queue() {
static dispatch_queue_t network_assistant_queue;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
network_assistant_queue = dispatch_queue_create("cn.yoho.analytics.network.queue", DISPATCH_QUEUE_SERIAL);
});
return network_assistant_queue;
}
@implementation YHNetworkAssistant
{
NSString *_hostName;
NSString *_apiPath;
NSMutableDictionary *_customHeaders;
}
#pragma mark - Init
+ (instancetype)sharedInstance
{
static YHNetworkAssistant *_sharedInstance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_allOperations = [NSMutableSet new];
_reachabilityChangedHandlers = [NSMutableArray array];
_sharedInstance = [[YHNetworkAssistant alloc] initWithHostName:kAnalizedURL apiPath:nil customHeaderFields:nil];
// 监听网络状态
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
NSLog(@"Reachability: %@", AFStringFromNetworkReachabilityStatus(status));
_currentNetworkStatus = status;
for (int i = 0; i < [_reachabilityChangedHandlers count]; i++) {
void(^aHandler)(AFNetworkReachabilityStatus status) = [_reachabilityChangedHandlers objectAtIndex:i];
aHandler(status);
}
}];
[[AFNetworkReachabilityManager sharedManager] startMonitoring];
});
return _sharedInstance;
}
- (id)init
{
return [self initWithHostName:nil apiPath:nil customHeaderFields:nil];
}
- (instancetype)initWithHostName:(NSString *)hostName
{
return [self initWithHostName:hostName apiPath:nil customHeaderFields:nil];
}
- (instancetype)initWithHostName:(NSString *)hostName customHeaderFields:(NSDictionary *)headers
{
return [self initWithHostName:hostName apiPath:nil customHeaderFields:headers];
}
- (instancetype)initWithHostName:(NSString *)hostName apiPath:(NSString *)apiPath customHeaderFields:(NSDictionary *)headers
{
if ((self = [super init])) {
_hostName = hostName;
_apiPath = apiPath;
if(headers && !headers[@"User-Agent"])
{
NSMutableDictionary *newHeadersDict = [headers mutableCopy];
NSString *userAgentString = [NSString stringWithFormat:@"%@/%@",
[[NSBundle mainBundle] infoDictionary][(NSString *)kCFBundleNameKey],
[[NSBundle mainBundle] infoDictionary][(NSString *)kCFBundleVersionKey]];
newHeadersDict[@"User-Agent"] = userAgentString;
_customHeaders = newHeadersDict;
}
else
{
_customHeaders = [headers mutableCopy];
}
if (!_customHeaders)
{
_customHeaders = [NSMutableDictionary dictionary];
}
}
return self;
}
#pragma mark - Network Reachability
- (BOOL)isReachable
{
return _currentNetworkStatus > AFNetworkReachabilityStatusNotReachable;
}
- (BOOL)isReachableWifi
{
return _currentNetworkStatus == AFNetworkReachabilityStatusReachableViaWiFi;
}
- (void)addReachabilityChangedHandler:(void (^)(AFNetworkReachabilityStatus))reachabilityChangedHandler
{
dispatch_sync(network_assistant_queue(), ^{
[_reachabilityChangedHandlers addObject:[reachabilityChangedHandler copy]];;
});
}
#pragma mark - Operation
- (void)enqueueOperation:(AFHTTPRequestOperation *)requestOperation
{
dispatch_sync(network_assistant_queue(), ^{
[_allOperations addObject:requestOperation];
});
}
+ (void)removeOperation:(AFHTTPRequestOperation *)aAperation
{
dispatch_sync(network_assistant_queue(), ^{
[_allOperations removeObject:aAperation];
});
}
+ (void)cancelOperationsFrom:(id)requester
{
dispatch_sync(network_assistant_queue(), ^{
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
if (![evaluatedObject isKindOfClass:[AFHTTPRequestOperation class]]) {
return NO;
}
AFHTTPRequestOperation *operation = (AFHTTPRequestOperation *)evaluatedObject;
if (operation.identifier == requester) {
return YES;
}
return NO;
}];
NSSet *operationsToCancel = [_allOperations filteredSetUsingPredicate:predicate];
[operationsToCancel enumerateObjectsUsingBlock:^(id obj, BOOL *stop) {
AFHTTPRequestOperation *operation = (AFHTTPRequestOperation *)obj;
[operation cancel];
}];
[_allOperations minusSet:operationsToCancel];
});
}
#pragma mark - `GET`
- (void)getWithAPI:(NSString *)api parameters:(NSDictionary *)parameters from:(id)requester success:(void (^)(id responseObject))success failure:(void (^)(NSError *error))failure
{
NSMutableDictionary *actualParameters = [NSMutableDictionary dictionaryWithDictionary:parameters];
/*
actualParameters 里可以添加一些公用的参数,如平台等
*/
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
AFHTTPRequestOperation *reqOperation = [manager GET:[self assemblyURLWhithApi:api] parameters:actualParameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
if (success) {
[self operationSucceeded:operation responseObject:responseObject succeededHandler:success failedHandler:failure];
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error :%@", error);
[YHNetworkAssistant removeOperation:operation];
if (failure) {
failure(error);
}
}];
// 标识operation, 并加入处理队列
reqOperation.identifier = requester;
[self enqueueOperation:reqOperation];
}
#pragma mark - `POST`
- (void)postWithAPI:(NSString *)api parameters:(NSDictionary *)parameters from:(id)requester success:(void (^)(id responseObject))success failure:(void (^)(NSError *error))failure
{
[self postWithAPI:api parameters:parameters files:nil from:requester success:success failure:failure];
}
- (void)postWithAPI:(NSString *)api parameters:(NSDictionary *)parameters files:(NSDictionary *)files from:(id)requester success:(void (^)(id responseObject))success failure:(void (^)(NSError *error))failure
{
[self postWithAPI:api parameters:parameters files:files from:requester progressBlock:nil success:success failure:failure];
}
/**
* @param progressBlock 添加处理进度的回调
*/
- (void)postWithAPI:(NSString *)api parameters:(NSDictionary *)parameters files:(NSDictionary *)files from:(id)requester progressBlock:(void(^)(float progress))progressBlock success:(void (^)(id responseObject))success failure:(void (^)(NSError *error))failure
{
NSError *error = nil;
NSMutableDictionary *actualParameters = [NSMutableDictionary dictionaryWithDictionary:parameters];
/*
actualParameters 里可以添加一些公用的参数,如平台,权限信息等
*/
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:actualParameters options:0 error:&error];
if (error) {
NSLog(@"json parsing, connot convert to json for: %@\n code: %ld\n reason: %@", actualParameters, (long)[error code], [error localizedDescription]);
if (failure) {
failure(error);
}
return;
}
if (![self assemblyURLWhithApi:api]) {
if (failure) {
failure(error);
}
return;
}
NSString *parsJsonStr = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/plain"];
AFHTTPRequestOperation *requestOperation = nil;
NSDictionary *pars = @{@"_mlogs": kSafeValue(parsJsonStr)};
// 有文件
if (files && [files count]) {
requestOperation = [manager POST:[self assemblyURLWhithApi:api] parameters:pars constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
// 上传文件
for (NSString *key in files) {
NSURL *filePath = [NSURL fileURLWithPath:files[key]];
[formData appendPartWithFileURL:filePath name:key error:nil];
}
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
// 成功回调
if (success) {
[self operationSucceeded:operation responseObject:responseObject succeededHandler:success failedHandler:failure];
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
// 失败回调
#ifdef IS_TEST
NSString *parsJsonStr = [[NSString alloc] initWithData:operation.request.HTTPBody encoding:NSUTF8StringEncoding];
parsJsonStr = [parsJsonStr urlDecodedString];
NSLog(@"\nrequest url \n%@\n pars \n%@", operation.request.URL, parsJsonStr);
NSLog(@"接口请求出错 Error: %@", error);
#endif
[YHNetworkAssistant removeOperation:operation];
if (failure) {
failure(error);
}
}];
} else {
// 没有文件
requestOperation = [manager POST:[self assemblyURLWhithApi:api] parameters:pars success:^(AFHTTPRequestOperation *operation, id responseObject) {
if (success) {
[self operationSucceeded:operation responseObject:responseObject succeededHandler:success failedHandler:failure];
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
#ifdef IS_TEST
NSString *parsJsonStr = [[NSString alloc] initWithData:operation.request.HTTPBody encoding:NSUTF8StringEncoding];
parsJsonStr = [parsJsonStr urlDecodedString];
NSLog(@"\nrequest url \n%@\n pars \n%@", operation.request.URL, parsJsonStr);
NSLog(@"接口请求出错 Error: %@", error);
#endif
[YHNetworkAssistant removeOperation:operation];
if (failure) {
failure(error);
}
}];
}
// 设置上传进度的回调
[requestOperation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
if (progressBlock) {
CGFloat progress = 0.0f;
if (totalBytesExpectedToWrite!=0) {
progress = ((CGFloat)totalBytesWritten)/((CGFloat)totalBytesExpectedToWrite);
}
progressBlock(progress);
}
}];
requestOperation.identifier = requester;
[self enqueueOperation:requestOperation];
}
#pragma mark - 成功请求后统一解析数据
- (void)operationSucceeded:(AFHTTPRequestOperation *)operation responseObject:(NSDictionary *)responseObject
succeededHandler:(void (^)(id responseObject))succeededHandler failedHandler:(void (^)(NSError *error))failedHandler
{
[YHNetworkAssistant removeOperation:operation];
#ifdef IS_TEST
NSString *parsJsonStr = [[NSString alloc] initWithData:operation.request.HTTPBody encoding:NSUTF8StringEncoding];
parsJsonStr = [parsJsonStr urlDecodedString];
NSLog(@"\nrequest url \n%@\n pars \n%@", operation.request.URL, parsJsonStr);
NSLog(@"Success: %@", responseObject);
#endif
if (![responseObject isKindOfClass:[NSDictionary class]]) {
succeededHandler(responseObject);
return;
}
/*
此处可以对一些公用的返回字段进行处理,如status, code, message等,需和服务器人员共同制定
•••
*/
NSInteger responseStatus = 0;
if ([responseObject.allKeys containsObject:@"status"])
{
responseStatus = [[responseObject objectForKey:@"status"] integerValue];
}
if (responseStatus != 0 ) {
NSInteger responseCode = 0;
if ([responseObject.allKeys containsObject:@"code"]) {
responseCode = [[responseObject objectForKey:@"code"] integerValue];
}
NSString *localizedDescription = [responseObject objectForKey:@"message"];
NSDictionary* dataDic = [responseObject objectForKey:@"data"];
NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:localizedDescription, NSLocalizedDescriptionKey, kSafeValue(dataDic), @"data", nil];
NSError *error = [NSError errorWithDomain:YHEAPIErrorDomain code:responseCode userInfo:userInfo];
if (failedHandler) {
failedHandler(error);
}
} else {
NSDictionary *responseJSON = [responseObject objectForKey:@"data"];
if([responseJSON isKindOfClass:[NSArray class]] && 0 == [(NSArray*)responseJSON count]) {
responseJSON = nil;
}
succeededHandler(responseJSON);
}
}
#pragma mark - Pravite method
- (NSString *)assemblyURLWhithApi:(NSString *)api
{
NSMutableString *apiUrl = [NSMutableString stringWithString:@""];
if (_hostName && _hostName.length) {
[apiUrl appendFormat:@"%@%@", _hostName, (_apiPath.length) ? @"/" : @""];
}
if (_apiPath && _apiPath.length) {
[apiUrl appendFormat:@"%@%@", _apiPath, (api.length) ? @"/" : @""];
}
if (api && api.length) {
[apiUrl appendFormat:@"%@", api];
}
if (apiUrl.length < 1 || ![apiUrl hasPrefix:@"http"]) {
NSLog(@"ERROR YHENetworkEngine: 接口请求的URL不正确: %@", apiUrl);
NSLog(@"调用堆栈 %@", [NSThread callStackSymbols]);
return nil;
}
return apiUrl;
}
@end
//
// YHNetworkService.h
// YH_Analytics
//
// Created by Zhou Rongjun on 15/4/27.
// Copyright (c) 2015年 YOHO. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "AFNetworking.h"
typedef void (^YHNetworkReachabilityStatusBlock)(AFNetworkReachabilityStatus status);
@interface YHNetworkService : NSObject
+ (instancetype)sharedInstance;
- (void)setReachabilityStatusChangeBlock:(YHNetworkReachabilityStatusBlock)block;
- (AFHTTPRequestOperation *)uploadLogData:(NSDictionary *)parameters completionBlock:(void (^)(BOOL success, NSError *error))block;
@end
... ...
//
// YHNetworkService.m
// YH_Analytics
//
// Created by Zhou Rongjun on 15/4/27.
// Copyright (c) 2015年 YOHO. All rights reserved.
//
#import "YHNetworkService.h"
#define kSafeValue(X) (!(X) ? [NSNull null] : (X))
#define kURLAnalyticsService @"http://analytics.yhurl.com/"
#define kYASApiMethod @"yas_mobile"
@interface YHNetworkService ()
@property (strong, nonatomic) AFHTTPRequestOperationManager *httpClient;
@property (readwrite, nonatomic, copy) YHNetworkReachabilityStatusBlock networkReachabilityStatusBlock;
@end
@implementation YHNetworkService
+ (instancetype)sharedInstance
{
static YHNetworkService *_sharedInstance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedInstance = [[YHNetworkService alloc] init];
});
return _sharedInstance;
}
- (id)init
{
self = [super init];
if (self) {
self.httpClient = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:[NSURL URLWithString:kURLAnalyticsService]];
self.httpClient.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/plain"];
self.httpClient.securityPolicy.allowInvalidCertificates = YES;
self.httpClient.operationQueue.maxConcurrentOperationCount = 6;
}
return self;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[self.httpClient.reachabilityManager stopMonitoring];
self.networkReachabilityStatusBlock = nil;
self.httpClient = nil;
}
- (void)setReachabilityStatusChangeBlock:(void (^)(AFNetworkReachabilityStatus status))block
{
self.networkReachabilityStatusBlock = block;
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleNetworkReachabilityStatusChanged:) name:AFNetworkingReachabilityDidChangeNotification object:nil];
[self.httpClient.reachabilityManager startMonitoring];
}
- (AFHTTPRequestOperation *)uploadLogData:(NSDictionary *)parameters completionBlock:(void (^)(BOOL success, NSError *error))block
{
NSError *error = nil;
NSMutableDictionary *actualParameters = [NSMutableDictionary dictionaryWithDictionary:parameters];
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:actualParameters options:0 error:&error];
if (error) {
NSLog(@"json parsing, connot convert to json for: %@\n code: %ld\n reason: %@", actualParameters, (long)[error code], [error localizedDescription]);
if (block) {
block(NO, error);
}
return nil;
}
NSString *parsJsonStr = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSDictionary *newParameters = @{@"_mlogs": kSafeValue(parsJsonStr)};
return [self.httpClient POST:kYASApiMethod parameters:newParameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
if (block) {
block(YES, nil);
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
if (block) {
block(NO, error);
}
}];
}
- (void)handleNetworkReachabilityStatusChanged:(NSNotification *)notification
{
AFNetworkReachabilityStatus status = [[notification.userInfo objectForKey:AFNetworkingReachabilityNotificationStatusItem] integerValue];
if (self.networkReachabilityStatusBlock) {
self.networkReachabilityStatusBlock(status);
}
}
@end
... ...
... ... @@ -7,6 +7,7 @@
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "YHError.h"
#import "YHEvent.h"
... ...
... ... @@ -37,15 +37,21 @@
- (void)testMd5Method {
NSLog(@"%@ start", self.name);
[[mock stub] md5];
[[mock expect] md5];
[mock md5];
[mock verify];
NSLog(@"%@ end", self.name);
}
- (void)testUrlDecodedStringMethod {
NSLog(@"%@ start", self.name);
[[mock stub] urlDecodedString];
[[mock expect] urlDecodedString];
[mock urlDecodedString];
[mock verify];
NSLog(@"%@ end", self.name);
}
... ...
... ... @@ -16,6 +16,7 @@
#import "YHEvent.h"
#import "YHError.h"
#import "FakeLocationManager.h"
#import "YHNetworkService.h"
@interface YHAssemblyAssistant (XCTestCase)
... ... @@ -63,7 +64,7 @@
partialMock = OCMPartialMock(assembly);
networkMock = OCMClassMock([YHNetworkAssistant class]);
networkMock = OCMClassMock([YHNetworkService class]);
OCMStub([networkMock sharedInstance]).andReturn(networkMock);
}
... ... @@ -179,7 +180,7 @@
- (void)testPrepareImmediUploadDicWithNetworkReachabilityStatus {
NSLog(@"%@ start", self.name);
OCMExpect([networkMock addReachabilityChangedHandler:[OCMArg any]]);
OCMExpect([networkMock setReachabilityStatusChangeBlock:[OCMArg any]]);
[assembly prepareImmediUploadDic:@"appId" sessionId:@"sessionId"];
... ... @@ -355,7 +356,7 @@
[assembly prepareImmediUploadDic:@"appId" sessionId:@"sessionId"];
YHEvent *data = [YHEvent new];
data.op = @"testEvent";
OCMExpect([networkMock postWithAPI:[OCMArg any] parameters:[OCMArg any] from:assembly success:[OCMArg any] failure:[OCMArg any]]);
OCMExpect([networkMock uploadLogData:[OCMArg any] completionBlock:[OCMArg any]]);
[assembly uploadImmedilyWithEvent:data];
... ... @@ -374,7 +375,7 @@
[assembly prepareImmediUploadDic:@"appId" sessionId:@"sessionId"];
YHError *data = [YHError new];
OCMExpect([networkMock postWithAPI:[OCMArg any] parameters:[OCMArg any] from:assembly success:[OCMArg any] failure:[OCMArg any]]);
OCMExpect([networkMock uploadLogData:[OCMArg any] completionBlock:[OCMArg any]]);
[assembly uploadImmedilyWithEvent:data];
... ... @@ -416,7 +417,7 @@
NSDictionary *uploadData = [NSDictionary dictionary];
OCMExpect([partialMock getUploadData]).andReturn(uploadData);
OCMExpect([networkMock postWithAPI:[OCMArg any] parameters:[OCMArg any] from:assembly success:[OCMArg any] failure:[OCMArg any]]);
OCMExpect([networkMock uploadLogData:[OCMArg any] completionBlock:[OCMArg any]]);
[assembly uploadDiskData];
... ... @@ -430,7 +431,7 @@
NSLog(@"%@ start", self.name);
OCMExpect([partialMock getUploadData]).andReturn(nil);
[[networkMock reject] postWithAPI:[OCMArg any] parameters:[OCMArg any] from:assembly success:[OCMArg any] failure:[OCMArg any]];
[[networkMock reject] uploadLogData:[OCMArg any] completionBlock:[OCMArg any]];
[assembly uploadDiskData];
... ... @@ -495,7 +496,7 @@
assembly.locationManager.delegate = assembly;
CLLocation *newLocation = [[CLLocation alloc] initWithLatitude:20.0f longitude:120.0f];
[[[partialMock expect] andReturnValue:@YES] updateLocation:newLocation];
OCMExpect([partialMock updateLocation:newLocation]).andReturn(YES);
OCMExpect([partialMock updateImmediUploadDic]);
[assembly prepareImmediUploadDic:@"appId" sessionId:@"seesionId"];
... ... @@ -513,7 +514,7 @@
assembly.locationManager.delegate = assembly;
CLLocation *newLocation = [[CLLocation alloc] initWithLatitude:20.0f longitude:120.0f];
[[[partialMock expect] andReturnValue:@NO] updateLocation:newLocation];
OCMExpect([partialMock updateLocation:newLocation]).andReturn(NO);
[[partialMock reject] updateImmediUploadDic];
[assembly prepareImmediUploadDic:@"appId" sessionId:@"seesionId"];
... ...
... ... @@ -34,7 +34,7 @@
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
NSLog(@"%@ setUp", self.name);
mock = [OCMockObject mockForClass:[YHAssemblyAssistant class]];
mock = OCMClassMock([YHAssemblyAssistant class]);
XCTAssertNotNil(mock, @"Cannot create YHAssemblyAssistant mock");
}
... ... @@ -82,9 +82,13 @@
- (void)testCanPersistingMethod {
NSLog(@"%@ start", self.name);
[[[mock expect] andReturnValue:@YES] canPersisting];
OCMExpect([mock canPersisting]).andReturn(YES);
BOOL bPersisting = [mock canPersisting];
XCTAssert(bPersisting, @"canPersisting doesn't return YES.");
OCMVerifyAll(mock);
NSLog(@"%@ end", self.name);
}
... ... @@ -92,8 +96,10 @@
NSLog(@"%@ start", self.name);
YHAnalyItemData *data = [[YHAnalyItemData alloc] init];
[[mock expect] saveItemData:data];
[mock saveItemData:data];
[mock verify];
NSLog(@"%@ end", self.name);
}
... ... @@ -104,6 +110,7 @@
[[[mock expect] andReturnValue:@10] getAllEventCount];
NSUInteger count = [mock getAllEventCount];
XCTAssertEqual(count, 10, @"YHAssemblyAssistant getAllEventCount doesn't return 10.");
[mock verify];
NSLog(@"%@ end", self.name);
}
... ... @@ -115,6 +122,7 @@
[[[mock expect] andReturn:data] getUploadData];
NSDictionary *returndata = [mock getUploadData];
XCTAssertEqualObjects(data, returndata, @"YHAssemblyAssistant getUploadData doesn't return a dictionary with key:value.");
[mock verify];
NSLog(@"%@ end", self.name);
}
... ... @@ -124,6 +132,7 @@
[[mock expect] prepareImmediUploadDic:@"appId" sessionId:@"sessionId"];
[mock prepareImmediUploadDic:@"appId" sessionId:@"sessionId"];
[mock verify];
NSLog(@"%@ end", self.name);
}
... ... @@ -133,6 +142,7 @@
[[mock expect] uploadDiskData];
[mock uploadDiskData];
[mock verify];
NSLog(@"%@ end", self.name);
}
... ... @@ -143,6 +153,7 @@
YHAnalyItemData *data = [[YHAnalyItemData alloc] init];
[[mock expect] uploadImmedilyWithEvent:data];
[mock uploadImmedilyWithEvent:data];
[mock verify];
NSLog(@"%@ end", self.name);
}
... ...
... ... @@ -10,10 +10,13 @@
#import <XCTest/XCTest.h>
#import "OCMock.h"
#import "YHCrashReporter.h"
#import "YH_Analytics.h"
@interface YHCrashReporterTests : XCTestCase{
@private
id mock;
YHCrashReporter *crashReporter;
id partialMock;
id analyticsMock;
}
@end
... ... @@ -24,19 +27,142 @@
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
NSLog(@"%@ setUp", self.name);
mock = [OCMockObject mockForClass:[YHCrashReporter class]];
XCTAssertNotNil(mock, @"Cannot create YHCrashReporter mock");
crashReporter = [YHCrashReporter new];
partialMock = OCMPartialMock(crashReporter);
XCTAssertNotNil(crashReporter, @"Cannot create YHCrashReporter instance");
analyticsMock = OCMClassMock([YH_Analytics class]);
OCMStub([analyticsMock sharedInstance]).andReturn(analyticsMock);
}
- (void)tearDown {
// Put teardown code here. This method is called after the invocation of each test method in the class.
mock = nil;
partialMock = nil;
crashReporter = nil;
analyticsMock = nil;
[super tearDown];
}
- (void)testExample {
// This is an example of a functional test case.
XCTAssert(YES, @"Pass");
#pragma mark - 方法存在性验证
- (void)testCallstackAsArrayMethod {
NSLog(@"%@ start", self.name);
OCMExpect([partialMock callstackAsArray]);
[crashReporter callstackAsArray];
OCMVerifyAll(partialMock);
NSLog(@"%@ end", self.name);
}
- (void)testHandleSignalMethod {
NSLog(@"%@ start", self.name);
OCMExpect([partialMock handleSignal:[OCMArg isKindOfClass:[NSDictionary class]]]);
[crashReporter handleSignal:@{@"key" : @"value"}];
OCMVerifyAll(partialMock);
NSLog(@"%@ end", self.name);
}
- (void)testHandleNSExceptionMethod {
NSLog(@"%@ start", self.name);
OCMExpect([partialMock handleNSException:[OCMArg isKindOfClass:[NSDictionary class]]]);
[crashReporter handleNSException:@{@"key" : @"value"}];
OCMVerifyAll(partialMock);
NSLog(@"%@ end", self.name);
}
#pragma mark - 行为测试
#pragma mark -
- (void)testCallstackAsArrayMethodReturnNotNil {
NSLog(@"%@ start", self.name);
NSLog(@"%@ end", self.name);
}
#pragma mark -
- (void)testHandleSignalMethodWithInputNil {
NSLog(@"%@ start", self.name);
[[analyticsMock reject] logError:[OCMArg any] parameters:[OCMArg any]];
[crashReporter handleSignal:nil];
[analyticsMock verify];
NSLog(@"%@ end", self.name);
}
- (void)testHandleSignalMethodWithInputInvalid {
NSLog(@"%@ start", self.name);
[[analyticsMock reject] logError:[OCMArg any] parameters:[OCMArg any]];
[crashReporter handleSignal:nil];
[analyticsMock verify];
NSLog(@"%@ end", self.name);
}
- (void)testHandleSignalMethodWithInputDictionary {
NSLog(@"%@ start", self.name);
NSDictionary *userInfo = [NSDictionary dictionary];
[[analyticsMock expect] logError:@"CRASH" parameters:@{JsonKeyErrorST : userInfo}];
[crashReporter handleSignal:userInfo];
[analyticsMock verify];
NSLog(@"%@ end", self.name);
}
#pragma mark -
- (void)testHandleNSExceptionMethodWithInputNil {
NSLog(@"%@ start", self.name);
[[analyticsMock reject] logError:[OCMArg any] parameters:[OCMArg any]];
[crashReporter handleNSException:nil];
[analyticsMock verify];
NSLog(@"%@ end", self.name);
}
- (void)testHandleNSExceptionMethodWithInputInvalid {
NSLog(@"%@ start", self.name);
[[analyticsMock reject] logError:[OCMArg any] parameters:[OCMArg any]];
[crashReporter handleNSException:nil];
[analyticsMock verify];
NSLog(@"%@ end", self.name);
}
- (void)testHandleNSExceptionMethodWithInputDictionary {
NSLog(@"%@ start", self.name);
NSDictionary *userInfo = [NSDictionary dictionary];
[[analyticsMock expect] logError:@"CRASH" parameters:@{JsonKeyErrorST : userInfo}];
[crashReporter handleNSException:userInfo];
[analyticsMock verify];
NSLog(@"%@ end", self.name);
}
@end
... ...
//
// YHNetworkAssistantTests.m
// YHNetworkServiceTests.m
// YH_Analytics
//
// Created by Zhou Rongjun on 15/4/15.
// Created by Zhou Rongjun on 15/4/28.
// Copyright (c) 2015年 YOHO. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <XCTest/XCTest.h>
#import "OCMock.h"
#import "YHNetworkAssistant.h"
#import "YHNetworkService.h"
@interface YHNetworkAssistantTests : XCTestCase
@interface YHNetworkServiceTests : XCTestCase
@end
@implementation YHNetworkAssistantTests
@implementation YHNetworkServiceTests
- (void)setUp {
[super setUp];
... ... @@ -32,4 +31,11 @@
XCTAssert(YES, @"Pass");
}
- (void)testPerformanceExample {
// This is an example of a performance test case.
[self measureBlock:^{
// Put the code you want to measure the time of here.
}];
}
@end
... ...
... ... @@ -42,6 +42,7 @@
[[mock expect] startWithAppId:[OCMArg isKindOfClass:[NSString class]]];
[mock startWithAppId:@"appId"];
[mock verify];
NSLog(@"%@ end", self.name);
}
... ... @@ -50,7 +51,8 @@
NSLog(@"%@ start", self.name);
[[mock expect] logEvent:[OCMArg isKindOfClass:[NSString class]] parameters:[OCMArg isKindOfClass:[NSDictionary class]]];
[mock logEvent:@"event" parameters:nil];
[mock logEvent:@"event" parameters:@{@"key":@"value"}];
[mock verify];
NSLog(@"%@ end", self.name);
}
... ... @@ -59,7 +61,8 @@
NSLog(@"%@ start", self.name);
[[mock expect] logError:[OCMArg isKindOfClass:[NSString class]] parameters:[OCMArg isKindOfClass:[NSDictionary class]]];
[mock logError:@"error" parameters:nil];
[mock logError:@"error" parameters:@{@"key":@"value"}];
[mock verify];
NSLog(@"%@ end", self.name);
}
... ... @@ -69,6 +72,7 @@
[[mock expect] updateLogStrategy:LogStrategyCustom customInterval:1000];
[mock updateLogStrategy:LogStrategyCustom customInterval:1000];
[mock verify];
NSLog(@"%@ end", self.name);
}
... ... @@ -79,6 +83,7 @@
[[mock expect] uid];
[mock uid];
[mock verify];
NSLog(@"%@ end", self.name);
}
... ... @@ -88,6 +93,7 @@
[[mock expect] channelId];
[mock channelId];
[mock verify];
NSLog(@"%@ end", self.name);
}
... ... @@ -97,6 +103,7 @@
[[mock expect] logStrategy];
[mock logStrategy];
[mock verify];
NSLog(@"%@ end", self.name);
}
... ... @@ -106,6 +113,7 @@
[[mock expect] currentInterval];
[mock currentInterval];
[mock verify];
NSLog(@"%@ end", self.name);
}
... ... @@ -115,6 +123,7 @@
[[mock expect] event];
[mock event];
[mock verify];
NSLog(@"%@ end", self.name);
}
... ... @@ -124,6 +133,7 @@
[[mock expect] error];
[mock error];
[mock verify];
NSLog(@"%@ end", self.name);
}
... ...