1,mock單例:
單例類OKDataManager 有模型屬性userModel 通過mock單例設(shè)置固定的userModel屬性userId
id mockManager = OCMClassMock([OKDataManager class]);
//返回的是自身
OCMStub([mockManager shareManager]).andReturn(mockManager);
OKUserInfoModel *userModel = [[OKUserInfoModel alloc] init];
userModel.userId = @"123456"; //在測試調(diào)用的地方userId返回的就是123456
OKDataManager *manager = [OKDataManager shareManager];
OCMStub([manager userInfoModel]).andReturn(userModel);
2,reject 表示不執(zhí)行某個方法
工程中要測試的方法:
- (void)searchByMsg:(NSString *)msg {
if (!msg.length) {
return;
}
[self requestSearchByMsg:msg];
}
測試類中:
- (void)setUp {
[super setUp];
_vc = [[SearchVC alloc] init];
_mockVC = OCMPartialMock(_vc);
}
//調(diào)用測試方法,因?yàn)樗阉鞯膬?nèi)容為nil拂苹,所以斷言沒有調(diào)用- (void)requestSearchByMsg:方法
- (void)testSearchWithoutMsg {
[_mockVC searchByMsg:nil];
OCMExpect([[_mockVC reject] requestSearchByMsg:[OCMArg any]];
}
3燃异,測試控制器跳轉(zhuǎn)方法
//需要測試的工程代碼
- (void)pushWithOrderId:(NSString *)orderId {
DetailVC *detailVC = [[DetailVC alloc] init];
detailVC.ID = orderId;
[self.navigationController pushViewController:detailVC animated:YES];
}
//測試代碼
- (void)testPushWithOrderId {
//當(dāng)前控制器
ViewController *vc = [[ViewController alloc] init];
id mockVC = OCMPartialMock(vc);
//mock一個導(dǎo)航控制器
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:mockVC];
//調(diào)用要測試的方法
[mockVC pushToServiceOrderWithOrderId:@"0123"];
//驗(yàn)證是否調(diào)用了push方法
OCMVerify([[mockVC navigationController] pushViewController:[OCMArg any] animated:YES]);
//但是不能驗(yàn)證跳轉(zhuǎn)后的控制器類型,目前只做到方法是否調(diào)用
// XCTAssertTrue([navigationController.topViewController isKindOfClass:[DetailVC class]]);
}
4坏为,需要測試的工程類的私有變量和方法可以通過在測試工程類中添加工程類的分類方法和屬性變量來實(shí)現(xiàn)鲸匿,在測試工程中雁社,調(diào)用工程類的私有變量和方法.設(shè)置屬性時(shí),也可以通過setValue: forKey:來設(shè)置私有變量.
//工程中VCClass要測試的方法
@interface OKDataHotVC ()
@property (nonatomic, strong) TypeView *typeView; //私有變量
@property (nonatomic, strong) NSArray *types; //私有變量
@end
@implementation VCClass
//要測試的方法 ,typeView, types為控制器私有變量
- (void)showTypeView:(id)sender {
if (self.typeView.isShowed) {
[self.typeView hideWithAnimation:YES];
}
else {
[self.typeView showInSuperView:self.view animation:YES];
}
}
@end
//測試工程中
@interface VCClass (Test)
//添加VCClass類的私有變量,通過分類實(shí)現(xiàn)types的測試工程引用
@property (nonatomic, strong) NSArray *types;
//添加AClass類的私有方法
- (void)showTypeView:(id)sender;
@end
@interface AClassTest : XCTestCase
@end
@implementation AClassTest
- (void)setUp {
[super setUp];
}
- (void)tearDown {
[super tearDown];
}
//通過setValue: forKey:來設(shè)置私有變量typeView
- (void)testShowTypeViewForHide {
VCClass *vc = [[VCClass alloc] init];
id typeViewMock = OCMClassMock([TypeView class]);
//給vc的私有變量typeView賦值
[vc setValue: typeViewMock forKey:@"typeView"];
//設(shè)置為已經(jīng)顯示晒骇,調(diào)用隱藏的方法
OCMStub([typeViewMock isShowed]).andReturn(YES);
[vc showTypeView:nil];
OCMVerify([typeViewMock hideWithAnimation:YES]);
}
@end
5,測試添加通知的方法
工程中要測試的方法:
- (void)methodWithPostNotification {
//balalaba 執(zhí)行代碼.....
[[NSNotificationCenter defaultCenter] postNotificationName:@"name" object:nil];
}
測試方法中:
- (void)testPostNotification {
ViewController *vc = [[ViewController alloc] init];
id observerMock = OCMObserverMock();
//給通知中心設(shè)置觀察者
[[NSNotificationCenter defaultCenter] addMockObserver: observerMock name:@"name" object:nil];
//設(shè)置觀察期望
[[observerMock expect] notificationWithName:@"name" object:[OCMArg any]];
//調(diào)用要驗(yàn)證的方法
[vc methodWithPostNotification];
// 調(diào)用驗(yàn)證
OCMVerifyAll(popObserverMock);
}
6,mock Block回調(diào)事件
如果請求的回調(diào)是通過block實(shí)現(xiàn)洪囤,可以不用請求后臺數(shù)據(jù)徒坡,通過mock模擬回調(diào)數(shù)據(jù)
工程中請求類Request方法:
+ (void) requestDataByModel:(RequestModel*)requestModel completeBlock:(void(^)(BOOL result, NSString *code ,NSString *msg))completeBlock
{
requestModel.requestUrl = HTTP_FOR_Data_URL;
[RequestTools sendRequest:requestModel success:^(id returnValue) {
NSDictionary *dic = [returnValue ok_dictionary];
NSString *msg = [dic objectForKey:@"msg"];
NSString *code = [dic objectForKey:@"code"];
if ([code isEqualToString:@"0"]) {
if (completeBlock) {
completeBlock(YES, code, msg);
}
}
else{
if (completeBlock) {
completeBlock(NO, code, msg);
}
}
} failure:^(NSError *error) {
if (completeBlock) {
completeBlock(NO, @"1000", @"");
}
}];
}
工程中控制器ViewController中調(diào)用請求的方法(即需要測試的方法):
- (void)requestDataById:(NSString *)Id {
if(Id.length == 0){
return;
}
RequestModel *model = [[RequestModel alloc] init];
[Request requestDataByModel: model completeBlock:^(BOOL result, NSString *code ,NSString *msg ){
if(result){
NSLog(@"do something for correct situation:%@",msg);
[self doSomethingCorrectly];
}
else {
NSLog(@"do something for error situation:%@",msg);
[self doSomethingWrong];
}
}];
}
測試工程中:
//測試方法
- (void)testRequestDataById {
ViewController *vc = [[ViewController alloc] init];
//部分mock,需要驗(yàn)證vc是否調(diào)用方法
id mockVC = OCMPartialMock(vc);
//mock請求類
id mockRequest = OCMClassMock([Request class]);
//mock block數(shù)據(jù)
OCMStub([mockRequest requestDataByModel:[OCMArg any] completeBlock:[OCMArg any]]).andDo(^(NSInvocation *invocation){
void (^resultResponse)(BOOL result, NSString *code, NSString *msg);
//第0個和第1個參數(shù)是self,SEL,第2個是model,第3才是block
[invocation getArgument:&resultResponse atIndex:3];
//4. 設(shè)置返回?cái)?shù)據(jù)
resultResponse(YES,@"0",@"成功");
});
//調(diào)用要驗(yàn)證的方法,沒有id時(shí),通過reject驗(yàn)證不調(diào)用請求方法
[mockVC requestDataById:nil];
OCMVerify([[mockRequest reject] requestDataByModel:[OCMArg any] completeBlock:[OCMArg any]]);
//調(diào)用要驗(yàn)證的方法,有id
[mockVC requestDataById:@"123"];
//驗(yàn)證是否調(diào)用相應(yīng)的方法
OCMVerify([mockVC doSomethingCorrectly]);
}