Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to correctly test mapping with RestKit (nested mapping, to-many)
    primarykey
    data
    text
    <p>I'm trying to test response mapping of my Core Data model. I've got few classes in Core Data model but 2 of them I'm interesting to test. First class is <code>CTFUser</code> class which keep basic information about user, and the second one is a <code>CTFCharacter</code> class. User may have few characters (some sort of player) <strong>to-many relationship</strong>. What I want to do is write correctly test for <code>CTFUser</code> class and relationship between <code>CTFUser</code> and <code>CTFCharacter</code> class. When I wrote test without property <code>characters</code> which is <code>NSOrderedSet</code> type test passsed. When I try to test property <code>characters</code> without checking <code>value</code> of <code>RKPropertyMappingTestExpectation</code> test passes. But when I want to check value of this mapping I've got a crash. </p> <p><strong>JSON fixture used in test:</strong></p> <pre><code>{ "username": "tomkowz12", "email": "tmk.szlc@gmail.com", "password": "password123", "nick": "black_lord", "location": [10, 20], "characters" : [{ "type": 1, "total_time": 21, "total_score": 100, "health": 100, "level": 20, "is_active": 1 }, { "type": 2, "total_time": 23, "total_score": 98, "health": 55, "level": 12, "is_active": 0 }] } </code></pre> <p><strong>CTFUser class</strong></p> <pre><code>@interface CTFUser : CustomManagedObject @property (nonatomic, retain) NSString * email; @property (nonatomic, retain) NSString * nick; @property (nonatomic, retain) NSString * username; @property (nonatomic, retain) NSString * password; @property (nonatomic, retain) id location; @property (nonatomic, retain) CTFGame *game; @property (nonatomic, retain) NSOrderedSet *characters; + (NSDictionary *)dictionaryForResponseMapping; @end </code></pre> <p>and dictionary dictionary with attributes mapping for this class:</p> <pre><code>+ (NSDictionary *)dictionaryForResponseMapping { return @{@"username" : @"username", @"email" : @"email", @"password" : @"password", @"nick" : @"nick", @"location" : @"location"}; } </code></pre> <p><strong>CTFCharacter class</strong></p> <pre><code>@interface CTFCharacter : CustomManagedObject @property (nonatomic, retain) NSNumber * type; @property (nonatomic, retain) NSNumber * totalTime; @property (nonatomic, retain) NSNumber * totalScore; @property (nonatomic, retain) NSNumber * health; @property (nonatomic, retain) NSNumber * level; @property (nonatomic, retain) NSNumber * active; @property (nonatomic, retain) CTFUser *user; + (NSDictionary *)dictionaryResponseMapping; @end </code></pre> <p>And dictionary with attributes mapping:</p> <pre><code>+ (NSDictionary *)dictionaryResponseMapping { return @{@"type": @"type", @"total_time": @"totalTime", @"total_score": @"totalScore", @"health": @"health", @"level": @"level", @"is_active": @"active"}; } </code></pre> <p>** Unit Test ** - (void)testUserResponseMApping { id parsedJSON = [RKTestFixture parsedObjectWithContentsOfFixture:@"user-response.json"];</p> <pre><code> /// Configure mapping RKEntityMapping *userMapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([CTFUser class]) inManagedObjectStore:_manager.managedObjectStore]; [userMapping addAttributeMappingsFromDictionary:[CTFUser dictionaryForResponseMapping]]; RKEntityMapping *characterMapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([CTFCharacter class]) inManagedObjectStore:_manager.managedObjectStore]; [characterMapping addAttributeMappingsFromDictionary:[CTFCharacter dictionaryResponseMapping]]; [userMapping addRelationshipMappingWithSourceKeyPath:@"characters" mapping:characterMapping]; /// Configure expectations RKMappingTest *test = [RKMappingTest testForMapping:userMapping sourceObject:parsedJSON destinationObject:nil]; test.managedObjectContext = _service.managedObjectContext; RKPropertyMappingTestExpectation *usernameExpectation = [RKPropertyMappingTestExpectation expectationWithSourceKeyPath:@"username" destinationKeyPath:@"username" value:@"tomkowz12"]; [test addExpectation:usernameExpectation]; RKPropertyMappingTestExpectation *emailExpectation = [RKPropertyMappingTestExpectation expectationWithSourceKeyPath:@"email" destinationKeyPath:@"email" value:@"tmk.szlc@gmail.com"]; [test addExpectation:emailExpectation]; RKPropertyMappingTestExpectation *passwordExpectation = [RKPropertyMappingTestExpectation expectationWithSourceKeyPath:@"password" destinationKeyPath:@"password" value:@"password123"]; [test addExpectation:passwordExpectation]; RKPropertyMappingTestExpectation *nickExpectation = [RKPropertyMappingTestExpectation expectationWithSourceKeyPath:@"nick" destinationKeyPath:@"nick" value:@"black_lord"]; [test addExpectation:nickExpectation]; RKPropertyMappingTestExpectation *locationExpectation = [RKPropertyMappingTestExpectation expectationWithSourceKeyPath:@"location" destinationKeyPath:@"location" value:@[@(10), @(20)]]; [test addExpectation:locationExpectation]; /// Configure expectation objects CTFCharacter *firstCharacter = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([CTFCharacter class]) inManagedObjectContext:_service.managedObjectContext]; firstCharacter.type = @(1); firstCharacter.totalTime = @(21); firstCharacter.totalScore = @(100); firstCharacter.health = @(100); firstCharacter.level = @(20); firstCharacter.active = @YES; CTFCharacter *secondCharacter = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([CTFCharacter class]) inManagedObjectContext:_service.managedObjectContext]; secondCharacter.type = @(2); secondCharacter.totalTime = @(23); secondCharacter.totalScore = @(98); secondCharacter.health = @(55); secondCharacter.level = @(12); secondCharacter.active = @NO; NSOrderedSet *set = [[NSOrderedSet alloc] initWithArray:@[firstCharacter, secondCharacter]]; RKPropertyMappingTestExpectation *charactersExpectation = [RKPropertyMappingTestExpectation expectationWithSourceKeyPath:@"characters" destinationKeyPath:@"characters" value:set]; /// &lt;-- this won't pass // [RKPropertyMappingTestExpectation expectationWithSourceKeyPath:@"characters" destinationKeyPath:@"characters"]; /// &lt;-- this pass [test addExpectation:charactersExpectation]; [test verify]; } </code></pre> <p><strong>Crash log</strong></p> <pre><code>&lt;unknown&gt;:0: error: -[CTFUserTests testUserResponseMApping] : mapped to unexpected _NSFaultingMutableOrderedSet value 'Relationship 'characters' on managed object (0x8c4fba0) &lt;CTFUser: 0x8c4fba0&gt; (entity: CTFUser; id: 0x8c4d2a0 &lt;x-coredata:///CTFUser/t28A63306-B2D2-41F5-A0C3-1BE85520B04710&gt; ; data: { characters = ( "0x8c52470 &lt;x-coredata:///CTFCharacter/t28A63306-B2D2-41F5-A0C3-1BE85520B04711&gt;", "0x8c4d330 &lt;x-coredata:///CTFCharacter/t28A63306-B2D2-41F5-A0C3-1BE85520B04712&gt;" ); email = "tmk.szlc@gmail.com"; game = nil; location = "(\n 10,\n 20\n)"; nick = "black_lord"; password = password123; username = tomkowz12; }) with objects {( &lt;CTFCharacter: 0x8c528f0&gt; (entity: CTFCharacter; id: 0x8c52470 &lt;x-coredata:///CTFCharacter/t28A63306-B2D2-41F5-A0C3-1BE85520B04711&gt; ; data: { active = 1; health = 100; level = 20; totalScore = 100; totalTime = 21; type = 1; user = "0x8c4d2a0 &lt;x-coredata:///CTFUser/t28A63306-B2D2-41F5-A0C3-1BE85520B04710&gt;"; }), &lt;CTFCharacter: 0x8c4ef60&gt; (entity: CTFCharacter; id: 0x8c4d330 &lt;x-coredata:///CTFCharacter/t28A63306-B2D2-41F5-A0C3-1BE85520B04712&gt; ; data: { active = 0; health = 55; level = 12; totalScore = 98; totalTime = 23; type = 2; user = "0x8c4d2a0 &lt;x-coredata:///CTFUser/t28A63306-B2D2-41F5-A0C3-1BE85520B04710&gt;"; }) )}' ( 0 CoreFoundation 0x021185e4 __exceptionPreprocess + 180 1 libobjc.A.dylib 0x01e9b8b6 objc_exception_throw + 44 2 CoreFoundation 0x021a86a1 -[NSException raise] + 17 3 Capture The FlagTests 0x0a0f1d60 -[RKMappingTest verifyExpectation:] + 464 4 Capture The FlagTests 0x0a0f2054 -[RKMappingTest verify] + 404 5 Capture The FlagTests 0x0a002cf0 -[CTFUserTests testUserResponseMApping] + 3648 6 CoreFoundation 0x0210cd1d __invoking___ + 29 7 CoreFoundation 0x0210cc2a -[NSInvocation invoke] + 362 8 XCTest 0x201032bf -[XCTestCase invokeTest] + 212 9 XCTest 0x2010338d -[XCTestCase performTest:] + 111 10 XCTest 0x2010417c -[XCTest run] + 82 11 XCTest 0x20102a44 -[XCTestSuite performTest:] + 139 12 XCTest 0x2010417c -[XCTest run] + 82 13 XCTest 0x20102a44 -[XCTestSuite performTest:] + 139 14 XCTest 0x2010417c -[XCTest run] + 82 15 XCTest 0x20102a44 -[XCTestSuite performTest:] + 139 16 XCTest 0x2010417c -[XCTest run] + 82 17 XCTest 0x20105aa1 +[XCTestProbe runTests:] + 183 18 Foundation 0x01ad212c __NSFireDelayedPerform + 372 19 CoreFoundation 0x020d6bd6 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 22 20 CoreFoundation 0x020d65bd __CFRunLoopDoTimer + 1181 21 CoreFoundation 0x020be628 __CFRunLoopRun + 1816 22 CoreFoundation 0x020bdac3 CFRunLoopRunSpecific + 467 23 CoreFoundation 0x020bd8db CFRunLoopRunInMode + 123 24 GraphicsServices 0x03ade9e2 GSEventRunModal + 192 25 GraphicsServices 0x03ade809 GSEventRun + 104 26 UIKit 0x00c09d3b UIApplicationMain + 1225 27 Capture The Flag 0x00008d0d main + 141 28 libdyld.dylib 0x0275670d start + 1 ) </code></pre> <p>Where I made mistake? How should be tested value of <code>characters</code> property? Other values are under the test and passed.</p> <p>edit:</p> <p><strong>When I made a request, response from server looks good, all properties and relationships are mapped correctly</strong>, but problem with testing still occurs.</p> <pre><code>- (void)getUser { CoreDataService *_service = [CoreDataService sharedInstance]; RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:_service.managedObjectModel]; _connection.manager.managedObjectStore = managedObjectStore; RKEntityMapping *userMapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([CTFUser class]) inManagedObjectStore:managedObjectStore]; [userMapping addAttributeMappingsFromDictionary:[CTFUser dictionaryForResponseMapping]]; RKEntityMapping *characterMapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([CTFCharacter class]) inManagedObjectStore:managedObjectStore]; [characterMapping addAttributeMappingsFromDictionary:[CTFCharacter dictionaryResponseMapping]]; [userMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"characters" toKeyPath:@"characters" withMapping:characterMapping]]; RKResponseDescriptor *descriptor = [RKResponseDescriptor responseDescriptorWithMapping:userMapping method:RKRequestMethodGET pathPattern:nil keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)]; [_connection.manager addResponseDescriptor:descriptor]; [_connection.manager getObject:nil path:@"test" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) { CTFUser *fetchedUser = (CTFUser *)mappingResult.firstObject; NSLog(@"%@", fetchedUser); } failure:^(RKObjectRequestOperation *operation, NSError *error) { NSLog(@"failure"); }]; } </code></pre> <p>Thank you in advance.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload