How to use OCMock to mock a service - ios

I am trying to write a unit test for creating a checklistItem, with properties defined below:
typedef NS_ENUM (NSUInteger, ChecklistStatus) { Pending, Completed };
#protocol IChecklistItem <NSObject>
#property (nonatomic, assign, readonly) NSInteger Id;
#property (nonatomic, copy, readonly) NSString *Description;
#property (nonatomic, assign, readonly)BOOL IsCompleted;
#property (nonatomic, assign, readwrite) ChecklistStatus Status;
#property (nonatomic, strong, readwrite) NSDate *CompletedDate;
#property (nonatomic, copy, readwrite) NSString *CompletedByUserId;
#property (nonatomic, assign, readonly) NSInteger RoleId;
#property (nonatomic, assign, readonly) NSInteger GroupId;
#property (nonatomic, strong, readonly) NSArray<IChecklistNote> *Notes;
Right now I have this setup in my setup method in my XCTest:
_service = [[ChecklistService alloc]initWithUrl:[NSURL URLWithString:kcChecklistUrl] credentialsManager:self.credentialsManager];
And this is the rest of my Unit Test:
- (void)testCreateChecklistItem {
XCTAssertNotNil(_service);
CCChecklistItem *checklistItem = [CCChecklistItem new];
CCChecklistItem *newChecklistItem = [CCChecklistItem new];
newChecklistItem.Id = 2;
newChecklistItem.Description = #"This is the Description";
newChecklistItem.RoleId = 2;
newChecklistItem.GroupId = 3;
newChecklistItem.Notes = nil;
newChecklistItem.Status = Completed;
XCTestExpectation *checklistItemExpectation = [self expectationWithDescription:#"checklistItem"];
id delegate = OCMProtocolMock(#protocol(ChecklistServiceDelegate));
id mock = [OCMockObject mockForProtocol:(#protocol(IChecklistService))];
[[[mock stub] andReturn:newChecklistItem] createChecklistItem:checklistItem delegate:delegate];
OCMExpect(([delegate didCompleteCreateChecklistItem:[OCMArg checkWithBlock:^BOOL(id obj) {
CCChecklistItem *items = obj;
XCTAssertNotNil(items);
double checklistId = items.Id;
XCTAssert(checklistId != 0);
[checklistItemExpectation fulfill];
}]]));
[_service createChecklistItem:checklistItem delegate:delegate];
[self waitForExpectationsWithTimeout:5 handler:^(NSError *error) {
if(error) {
}
OCMVerifyAll(delegate);
}];
}
However, i get the error failed: caught "NSUnknownKeyException", "[<__NSCFString 0x7faeaad6bd60> valueForUndefinedKey:]: this class is not key value coding-compliant for the key CompletedBy."
The createChecklistItem is defined below:
- (void)createChecklistItem:(id<IChecklistItem>)checklistItem delegate:(NSObject<ChecklistServiceDelegate> *)delegate
{
NSMutableArray *mockChecklistItem = [NSMutableArray new];
[TestObjectLoader loadObject:mockChecklistItem
fromJSONFile:#"ChecklistItem"
withMapping:[MappingProvider checklistCreateMapping]];
if (delegate != nil && [delegate respondsToSelector:#selector (didCompleteCreateChecklistItem:)]) {
[delegate didCompleteCreateChecklistItem:(NSObject<IChecklistItem> *)mockChecklistItem];
}
}
Where Checklist.json is
{
"Id": 13,
"Desc": "Checklist Description",
"IsCompleted": "false",
"TypeId": 1,
"RoleId": 1,
"Status": "C",
"CompletedDateTime": "2015-06-23T00:00:00+00:00",
"CompletedBy": "AC",
"Notes": [
{
"Note": "test",
"CreatedBy": "AC",
"CreatedDateTime": "2015-06-23T00:00:00+00:00"
}
]
}
Basically, I want to mock the service and when createChecklistItem is called, I simply just want to set a random Id on the object and pass it back instead of reading it through the ChecklistService from the Json file. IS there anyway to do this? I incorporated the mock in my test but I do not believe i am using it correctly...

You don't actually need Checklist.json, you should just be returning a value with a different Id.
So...
- (void)createChecklistItem:(id<IChecklistItem>)checklistItem delegate:(NSObject<ChecklistServiceDelegate> *)delegate
{
NSMutableArray *mockChecklistItem = [NSMutableArray new];
[TestObjectLoader loadObject:mockChecklistItem
fromJSONFile:#"ChecklistItem"
withMapping:[MappingProvider checklistCreateMapping]];
if (delegate != nil && [delegate respondsToSelector:#selector (didCompleteCreateChecklistItem:)]) {
[delegate didCompleteCreateChecklistItem:(NSObject<IChecklistItem> *)mockChecklistItem];
}
}
should simply just be
checklistItem.Id = 2; //Random number

Related

Creating a data model from JSON

I have a JSON that looks like this :
{
"club": [
{
"titles": "1",
"league": "epl",
"country": "england",
}
}
And I have created a property like this :
#property (strong, nonatomic) NSMutableArray <Clubs> *club;
The club property inherits from the Clubs class which has the titles, leagues and country properties.
When I try to create a dictionary with that data model, I am unable to access the properties inside the club array.
Am I creating the data model incorrectly ?
Creating the dictionary:
for (NSDictionary *dictionary in responseObject) {
if (![self.searchText isEqualToString:#""]) {
self.predictiveProductsSearch = [[PerdictiveSearch alloc]initWithDictionary:dictionary error:nil];
self.predictiveTableView.dataSource = self;
[self.predictiveTableView reloadData];
self.predictiveTableView.hidden = NO;
}
}
Clubs class
#import <JSONModel/JSONModel.h>
#protocol Clubs #end
#interface Clubs : JSONModel
#property (strong, nonatomic) NSString <Optional> * titles;
#property (strong, nonatomic) NSString <Optional> * league;
#property (strong, nonatomic) NSString <Optional> * country;
#property (strong, nonatomic) NSString <Optional> * topGS;
#property (strong, nonatomic) NSString <Optional> * GoalSc;
#property (strong, nonatomic) NSString <Optional> * TransferBudget;
#end
Please use below code to achieve JSON Model saving:
_club = [[NSMutableArray alloc]init];
NSDictionary *responseObject = #{
#"club": #[
#{
#"titles": #"1",
#"league": #"epl",
#"country": #"england"
}]
};
NSArray *newResponseObject = [responseObject objectForKey:#"club"];
for (NSDictionary *dictionary in newResponseObject) {
Clubs *objClubs = [[Clubs alloc]initWithDictionary:dictionary error:nil];
[_club addObject:objClubs];
}
NSLog(#"%#",[_club objectAtIndex:0]);
which print like below :
<Clubs>
[titles]: 1
[country]: england
[GoalSc]: <nil>
[league]: epl
[topGS]: <nil>
[TransferBudget]: <nil>
</Clubs>

Schema validation failed: Property declared as origin of linking objects property is not a link

I have two RLMObjects named RCRealmUser and RCRealmLocation. RCRealmUser has a one-to-one relationship defined on RCRealmLocation and RCRealmLocation has an inverse relation with the RCRealmUser. This is how I have defined these two:
RCRealmUser.h
#interface RCRealmUser : RLMObject
#property NSNumber <RLMInt> *userId;
#property NSString *username;
#property NSNumber <RLMInt> *countryCode;
#property NSNumber <RLMDouble> *phoneNumber;
#property NSString *fullName;
#property NSString *profileImageURL;
#property RCRealmLocation *location;
- (id)initWithMantleModel:(RCUserProfile *)user;
#end
RLM_ARRAY_TYPE(RCRealmUser)
RCRealmUser.m
#implementation RCRealmUser
+ (NSString *)primaryKey {
return #"userId";
}
+ (NSArray *)indexedProperties {
return #[#"fullName"];
}
+ (NSDictionary *)defaultPropertyValues {
return #{#"countryCode": #91};
}
- (id)initWithMantleModel:(RCUserProfile *)user {
self = [super init];
if(!self) return nil;
self.userId = user.userId;
self.username = user.username;
self.countryCode = user.countryCode;
self.phoneNumber = user.phoneNumber;
self.fullName = user.fullName;
self.profileImageURL = user.profileImageURL.absoluteString;
self.location = [[RCRealmLocation alloc] initWithMantleModel:user.location];
return self;
}
#end
RCRealmLocation.h
#interface RCRealmLocation : RLMObject
#property (readonly) RLMLinkingObjects *userId;
#property NSNumber <RLMDouble> *latitute;
#property NSNumber <RLMDouble> *longitude;
#property NSDate *timestamp;
#property NSNumber <RLMInt> *accuracy;
- (id)initWithMantleModel:(RCLocation *)location;
#end
RLM_ARRAY_TYPE(RCRealmLocation)
RCRealmLocation.m
#implementation RCRealmLocation
+ (NSArray<NSString *> *)indexedProperties {
return #[#"timestamp"];
}
+ (NSDictionary<NSString *,RLMPropertyDescriptor *> *)linkingObjectsProperties {
return #{#"userId": [RLMPropertyDescriptor descriptorWithClass:RCRealmUser.class propertyName:#"userId"]};
}
- (id)initWithMantleModel:(RCLocation *)location {
self = [super init];
if(!self) return nil;
self.latitute = location.latitute;
self.longitude = location.longitude;
self.timestamp = location.timestamp;
self.accuracy = location.accuracy;
return self;
}
Now when I try to insert into RCRealmUser I encounter an error
'RLMException', reason: 'Schema validation failed due to the following
errors:
Property 'userId' declared as origin of linking objects property 'userId' is not a link.'
Am I doing something wrong somewhere?
"Linking objects" properties must represent links (relationships).
In your case, you're saying that the RCRealmLocation.userId property should represent RCRealmUser objects that link to that location via its userId property. However, RCRealmUser.userId isn't a relationship to RCRealmLocation objects, it's an optional integer.
I believe what you want is a property on RCRealmLocation that refers to all RCRealmUsers linking to that location with its locations relationship. You can accomplishing this by changing your RCRealmLocation.userId property to this:
#property (readonly) RLMLinkingObjects *users;
and your linkingObjectsProperties implementation to this:
return #{#"users": [RLMPropertyDescriptor descriptorWithClass:RCRealmUser.class propertyName:#"location"]};
Read Realm's docs on inverse relationships for more information.

How to parse the category object recursively in parsed JSON

Hi I am getting parsed nested JSON, which has many levels. I am able to get at first level value.
How could i use same model class to fetch all nested JSON values using recursion.
My JSON is -
{
"message": "Ok",
"STATUS_CODE": "200",
"REQUEST": {
"userid": "12436124",
"command": "GETCATEGORY"
},
"RESPONSE": {
"Category": [
{
"type": "Tag",
"categoryId": 11,
"name": "Electronics",
"catIconLeft": "",
"catIconRight": "",
"parentId": 0,
"Category": [
{
"type": "Category",
"categoryId": 84,
"name": "Mobile Accessories",
"parentId": 1,
"catIconLeft": "",
"catIconRight": "",
"Category": [
{
"type": "Product",
"categoryId": 90,
"name": "Headsets",
"catIconLeft": "",
"catIconRight": "",
"parentId": 9
},
<----so on------>
The complete Parsed JSON LINK
My Code for parsing-
-(void)call_CategoryListData{
[params setObject:#"command" forKey:#"GETCATEGORY"];
[params setObject:#"userid" forKey:#"12436124"];
[serverCall actionmethod:Fake_Category parameters:params onComplete:^(NSMutableDictionary* results){
if ([results isKindOfClass:[NSDictionary class]] || [results isKindOfClass:[NSMutableDictionary class]]){
//DDLogVerbose(#"\n\n\n\n\nResult----->%#",results);
NSMutableDictionary*responseDic=[results objectForKey:#"RESPONSE"];
NSMutableArray*catArray=[responseDic objectForKey:#"Category"];
for (NSMutableDictionary *dic in catArray) {
NSMutableArray* tmp = [dic objectForKey:#"Category"];
if (tmp) {
MyCategory *cat = [[MyCategory alloc] init];
cat.type = dic[#"type"];
cat.categoryId = dic[#"categoryId"];
if ([cat.type isEqualToString:#"Tag"]) {
cat.name = dic[#"name"];
cat.categoryId = dic[#"categoryId"];
[CatTag addObject:cat.name];
[CatID addObject:cat.categoryId];
<---------so on --------------->
NSLog(#"New Objects--->%#\n\n----->%#",CatTag,CatID);
}
}
}
}
}
onError:^(NSError *error) {
// handle error here
}];
}
My Model Class-
#interface MyCategory : NSObject
#property (nonatomic, strong) NSString *type;
#property (nonatomic, strong) NSString *name;
#property (nonatomic, strong) NSString *categoryId;
#property(nonatomic,strong) NSString *catIconLeft;
#property (nonatomic,strong) NSString *catIconRight;
#property (nonatomic,strong) NSString *parentId;
#property (nonatomic, strong) MyCategory*Category;
MyCategory.h file
#interface MyCategory : NSObject
#property (nonatomic, strong) NSString *type;
#property (nonatomic, strong) NSString *name;
#property (nonatomic, strong) NSString *categoryId;
#property (nonatomic, strong) NSString *catIconLeft;
#property (nonatomic, strong) NSString *catIconRight;
#property (nonatomic, strong) NSString *parentId;
#property (nonatomic, strong) NSArray *categories;
- (id)initWithRootDictionary:(NSDictionary *)dictionary;
#end
MyCategory.m hile
#implementation
- (id)initWithRootDictionary:(NSDictionary *)dictionary
{
self = [super init];
self.type = dictionary[#"type"];
self.name = dictionary[#"name"];
self.categoryId = dictionary[#"categoryId"];
self.catIconLeft = dictionary[#"catIconLeft"];
self.catIconRight = dictionary[#"catIconRight"];
self.parentId = dictionary[#"parentId"];
if (dictionary[#"category"]) {
NSMutableArray *categories = [NSMutableArray new];
for (NSDictionary *cat in dictionary[#"category"]) {
MyCategory *category = [[MyCategory alloc] initWithRootDictionary:cat];
[categories addObject:category];
}
self.categories = categories;
}
return self;
}
#end
//...
-(void)call_CategoryListData
{
//...
NSMutableDictionary * responseDic = [results objectForKey:#"RESPONSE"];
NSMutableArray * catArray = [responseDic objectForKey:#"Category"];
NSMutableArray *result = [NSMutableArray new];
for (NSDictionary *categoryDic in catArray) {
MyCategory *category = [[MyCategory alloc] initWithRootDictionary:categoryDic];
[result addObject:category];
}
// Do something with result
}
This is a fast written code directly in this editor without any IDE, so possible some syntax errors :)

Can't store object in array

This is Apprecord class
#interface AppRecord : NSObject
#property (nonatomic, strong) NSString *appIcon;
#property (nonatomic, strong) NSString * name;
#property (nonatomic, strong) NSString * description;
#property (nonatomic, strong) NSString * location;
#property (nonatomic, strong) NSString * address;
#property (nonatomic, strong) NSString * contacts;
#property (nonatomic, strong) NSString * additional_info;
#property (nonatomic, strong) NSString * image;
#end
and I am parsing json adding to an object of App record class
#import "ParserClass.h"
#import "AppRecord.h"
#interface ParserClass ()
#property (nonatomic, strong) NSArray *appRecordList;
#property (nonatomic, strong) NSData *dataToParse;
#property (nonatomic, strong) NSMutableArray *workingArray;
#property (nonatomic, strong) AppRecord *workingEntry;
#property (nonatomic, strong) NSMutableString *workingPropertyString;
#property (nonatomic, strong) NSArray *elementsToParse;
#property (nonatomic, readwrite) BOOL storingCharacterData;
#end
#implementation ParserClass
- (id)initWithData:(NSData *)data
{
self = [super init];
if (self != nil)
{
_dataToParse = data;
}
return self;
}
- (void)main
{
self.workingArray = [NSMutableArray array];
self.workingPropertyString = [NSMutableString string];
self.workingArray=[[NSMutableArray alloc]init];
NSDictionary *allData=[NSJSONSerialization JSONObjectWithData:_dataToParse options:0 error:nil];
NSLog(#"%#",allData);
for (NSDictionary *dict in allData)
{
NSLog(#"dict====%#",dict);
self.workingEntry=[[AppRecord alloc]init];
self.workingEntry.name=[dict objectForKey:#"name"];
self.workingEntry.description=[dict objectForKey:#"description"];
self.workingEntry.location=[dict objectForKey:#"location"];
self.workingEntry.address=[dict objectForKey:#"address"];
self.workingEntry.contacts=[dict objectForKey:#"contacts"];
self.workingEntry.additional_info=[dict objectForKey:#"additional_info"];
self.workingEntry.image=[dict objectForKey:#"image"];
[self.workingArray addObject:self.workingEntry];
}
NSLog(#"WORKING ARRAY========%#",self.workingArray);// Not getting proper value of working array
self.workingArray = nil;
self.workingPropertyString = nil;
self.dataToParse = nil;
}
#end
My problem is not getting proper value of working array,it only stores description property,but it should store apprecord object,please help.
OUTPUT
alldata=
(
{
"additional_info" = "lOREN iPSUM";
address = "1972 Hillview St. Sarasota,FL 34239";
contacts = 8745674556;
description = "Very cute place, awesome wait staff, great food. I am here on vacation and it was an awesome place to go to after a day relaxing at the beach.";
id = 1;
image = "http://..";
location = "1972 Hillview St. Sarasota,FL 34239";
name = "Beer Tasting at Hurricane Hanks";
},
{
"additional_info" = gdfgdfg;
address = "Farrer Place, Sydney, New South Wales, Australia";
contacts = 3423423423423;
description = restataurant;
id = 16;
image = "http://..";
location = kolkata;
name = "mosco ";
}
)
WORKING ARRAY========(
"Very cute place, awesome wait staff, great food. I am here on vacation and it was an awesome place to go to after a day relaxing at the beach.",
restataurant
)
First object name== Beer Tasting at Hurricane Hanks
First you remove 2 time intialization of self.workingArray
And please replace
#property (nonatomic, strong) NSString * description;
deccription with some other name
To know the reason click this link
for (NSDictionary *dict in allData)
{
AppRecord *createAppRecord=[[AppRecord alloc]init];
//Do some thing
[self.workingArray addObject:createAppRecord];
}
I think it will be helpful to you.

iOS: Object returning *nil description* after alloc and init

Let me preface this question by saying that I believe it to be a memory management mistake on my end. I just can't seem to figure out why it is happening.
I have a viewcontroller and a model class named Part.
#import <Foundation/Foundation.h>
#interface Part : NSObject
#property (nonatomic, strong) NSString *name;
#property (nonatomic, strong) NSString *partType;
#property (nonatomic, strong) NSString *description;
#property (nonatomic, strong) NSNumber *price;
- (id)initWithName:(NSString *)name AndType:(NSString *)type;
#end
In the view controller I have a property set as follows:
#property (nonatomic, strong) Part *part;
In the init function of ViewController I create some static arrays and create objects out of them:
- (id)init {
self = [super init];
self.partList = [[NSMutableArray alloc] init];
NSArray *inputArray = #[#"Part1",
#"Part2",
#"Part3",
#"Part4",
#"Part5",
#"Part6",
#"Part7",
#"Part8"];
NSString *tempType = #"PartCategory";
// Add dummy static data
for (int i = 0; i < [inputArray count]; i++) {
Part *partInput = [[Part alloc] initWithName:[inputArray objectAtIndex:i] AndType:tempType];
//partInput.name = [inputArray objectAtIndex:i];
//partInput.partType = tempType;
NSLog(#"Inserting Part %#", partInput);
[self.partList addObject:partInput];
}
return self;
}
The NSLog I call in that loop returns Inserting Part *nil description* for every part. I just can't track down what is happening here.
EDIT: Here is the initWithName method from Part that the controller uses:
- (id)initWithName:(NSString *)name AndType:(NSString *)type {
if(self = [super init]) {
self.name = name;
self.partType = type;
}
return self;
}
When using %# to print NSObject, it calls debugDescription that by default calling the description method of that object and your Part object always have nil description.
You better solve this by changing the description property name to something else, because it conflicts with the description method of NSObject.
See also: NSObject description and debugDescription

Resources