Files
RestKit/Tests/Logic/ObjectMapping/RKObjectMappingTest.m

258 lines
12 KiB
Objective-C

//
// RKObjectMappingTest.m
// RestKit
//
// Created by Blake Watters on 6/8/12.
// Copyright (c) 2012 RestKit. All rights reserved.
//
#import "RKTestEnvironment.h"
#import "RKTestUser.h"
#import "RKObjectMappingOperationDataSource.h"
@interface RKObjectMappingTest : RKTestCase
@end
@implementation RKObjectMappingTest
- (void)tearDown
{
[RKObjectMapping setDefaultSourceToDestinationKeyTransformationBlock:nil];
}
- (void)testThatTwoMappingsWithTheSameAttributeMappingsButDifferentObjectClassesAreNotConsideredEqual
{
RKObjectMapping *mapping1 = [RKObjectMapping mappingForClass:[NSString class]];
RKObjectMapping *mapping2 = [RKObjectMapping mappingForClass:[NSNumber class]];
assertThatBool([mapping1 isEqualToMapping:mapping2], is(equalToBool(NO)));
}
- (void)testThatTwoMappingsForNilObjectClassAreConsideredEqual
{
RKObjectMapping *mapping1 = [RKObjectMapping mappingForClass:nil];
RKObjectMapping *mapping2 = [RKObjectMapping mappingForClass:nil];
assertThatBool([mapping1 isEqualToMapping:mapping2], is(equalToBool(YES)));
}
- (void)testThatTwoMappingsAreNotConsideredEqualIfOneHasNilObjectClass
{
RKObjectMapping *mapping1 = [RKObjectMapping mappingForClass:nil];
RKObjectMapping *mapping2 = [RKObjectMapping mappingForClass:[NSString class]];
assertThatBool([mapping1 isEqualToMapping:mapping2], is(equalToBool(NO)));
}
- (void)testThatRelationshipMappingsWithTheSameObjectClassAndNoAttributesAreConsideredEqual
{
RKObjectMapping *mapping1 = [RKObjectMapping mappingForClass:[NSString class]];
RKObjectMapping *mapping2 = [RKObjectMapping mappingForClass:[NSString class]];
assertThatBool([mapping1 isEqualToMapping:mapping2], is(equalToBool(YES)));
}
- (void)testThatTwoMappingsForTheSameObjectClassContainingIdenticalAttributeMappingsAreConsideredEqual
{
RKObjectMapping *mapping1 = [RKObjectMapping mappingForClass:[NSString class]];
[mapping1 addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"this" toKeyPath:@"that"]];
RKObjectMapping *mapping2 = [RKObjectMapping mappingForClass:[NSString class]];
[mapping2 addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"this" toKeyPath:@"that"]];
assertThatBool([mapping1 isEqualToMapping:mapping2], is(equalToBool(YES)));
}
- (void)testThatTwoMappingsForTheSameObjectClassContainingDifferingAttributeMappingsAreNotConsideredEqual
{
RKObjectMapping *mapping1 = [RKObjectMapping mappingForClass:[NSString class]];
[mapping1 addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"this" toKeyPath:@"that"]];
RKObjectMapping *mapping2 = [RKObjectMapping mappingForClass:[NSString class]];
[mapping2 addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"different" toKeyPath:@"that"]];
assertThatBool([mapping1 isEqualToMapping:mapping2], is(equalToBool(NO)));
}
- (void)testThatTwoMappingsWithEqualRelationshipMappingsAreConsideredEqual
{
RKObjectMapping *relationshipMapping1 = [RKObjectMapping mappingForClass:[NSSet class]];
RKObjectMapping *relationshipMapping2 = [RKObjectMapping mappingForClass:[NSSet class]];
RKObjectMapping *mapping1 = [RKObjectMapping mappingForClass:[NSString class]];
[mapping1 addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"this" toKeyPath:@"that" withMapping:relationshipMapping1]];;
RKObjectMapping *mapping2 = [RKObjectMapping mappingForClass:[NSString class]];
[mapping2 addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"this" toKeyPath:@"that" withMapping:relationshipMapping2]];;
assertThatBool([mapping1 isEqualToMapping:mapping2], is(equalToBool(YES)));
}
- (void)testThatTwoMappingsWithDifferingRelationshipMappingClassesAreNotConsideredEqual
{
RKObjectMapping *relationshipMapping1 = [RKObjectMapping mappingForClass:[NSSet class]];
RKObjectMapping *relationshipMapping2 = [RKObjectMapping mappingForClass:[NSNumber class]];
RKObjectMapping *mapping1 = [RKObjectMapping mappingForClass:[NSString class]];
[mapping1 addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"this" toKeyPath:@"that" withMapping:relationshipMapping1]];;
RKObjectMapping *mapping2 = [RKObjectMapping mappingForClass:[NSString class]];
[mapping2 addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"this" toKeyPath:@"that" withMapping:relationshipMapping2]];;
assertThatBool([mapping1 isEqualToMapping:mapping2], is(equalToBool(NO)));
}
- (void)testThatTwoMappingsWithDifferingRelationshipMappingKeyPathsAreNotConsideredEqual
{
RKObjectMapping *relationshipMapping1 = [RKObjectMapping mappingForClass:[NSSet class]];
RKObjectMapping *relationshipMapping2 = [RKObjectMapping mappingForClass:[NSSet class]];
RKObjectMapping *mapping1 = [RKObjectMapping mappingForClass:[NSString class]];
[mapping1 addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"this" toKeyPath:@"that" withMapping:relationshipMapping1]];;
RKObjectMapping *mapping2 = [RKObjectMapping mappingForClass:[NSString class]];
[mapping2 addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"this" toKeyPath:@"different" withMapping:relationshipMapping2]];;
assertThatBool([mapping1 isEqualToMapping:mapping2], is(equalToBool(NO)));
}
- (void)testThatAddingAPropertyMappingThatExistsInAnotherMappingTriggersException
{
RKObjectMapping *firstMapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
RKAttributeMapping *attributeMapping = [RKAttributeMapping attributeMappingFromKeyPath:@"this" toKeyPath:@"that"];
[firstMapping addPropertyMapping:attributeMapping];
RKObjectMapping *secondMapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
NSException *exception = nil;
@try {
[secondMapping addPropertyMapping:attributeMapping];
}
@catch (NSException *caughtException) {
exception = caughtException;
}
@finally {
expect(exception).notTo.beNil();
expect(exception.reason).to.equal(@"Cannot add a property mapping object that has already been added to another `RKObjectMapping` object. You probably want to obtain a copy of the mapping: `[propertyMapping copy]`");
}
}
- (void)testThatAddingAnArrayOfPropertyMappingsThatExistInAnotherMappingTriggersException
{
RKObjectMapping *firstMapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
RKAttributeMapping *attributeMapping = [RKAttributeMapping attributeMappingFromKeyPath:@"this" toKeyPath:@"that"];
[firstMapping addPropertyMapping:attributeMapping];
RKObjectMapping *secondMapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
NSException *exception = nil;
@try {
[secondMapping addPropertyMappingsFromArray:@[attributeMapping]];
}
@catch (NSException *caughtException) {
exception = caughtException;
}
@finally {
expect(exception).notTo.beNil();
expect(exception.reason).to.equal(@"One or more of the property mappings in the given array has already been added to another `RKObjectMapping` object. You probably want to obtain a copy of the array of mappings: `[[NSArray alloc] initWithArray:arrayOfPropertyMappings copyItems:YES]`");
}
}
- (void)testThatAddingAnArrayOfAttributeMappingsThatExistInAnotherMappingTriggersException
{
RKObjectMapping *firstMapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
RKAttributeMapping *attributeMapping = [RKAttributeMapping attributeMappingFromKeyPath:@"this" toKeyPath:@"that"];
[firstMapping addPropertyMapping:attributeMapping];
RKObjectMapping *secondMapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
NSException *exception = nil;
@try {
[secondMapping addAttributeMappingsFromArray:@[attributeMapping, @"stringValue"]];
}
@catch (NSException *caughtException) {
exception = caughtException;
}
@finally {
expect(exception).notTo.beNil();
expect(exception.reason).to.equal(@"One or more of the property mappings in the given array has already been added to another `RKObjectMapping` object. You probably want to obtain a copy of the array of mappings: `[[NSArray alloc] initWithArray:arrayOfPropertyMappings copyItems:YES]`");
}
}
#pragma mark - Key Transformations
- (void)testPropertyNameTransformationBlockForAttributes
{
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
[mapping setSourceToDestinationKeyTransformationBlock:^NSString *(RKObjectMapping *mapping, NSString *sourceKey) {
return [sourceKey uppercaseString];
}];
[mapping addAttributeMappingsFromArray:@[ @"name", @"rank" ]];
NSArray *expectedNames = @[ @"NAME", @"RANK" ];
expect([mapping.propertyMappingsByDestinationKeyPath allKeys]).to.equal(expectedNames);
}
- (void)testPropertyNameTransformationBlockForRelationships
{
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
[mapping setSourceToDestinationKeyTransformationBlock:^NSString *(RKObjectMapping *mapping, NSString *sourceKey) {
return [sourceKey uppercaseString];
}];
RKObjectMapping *relatedMapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
[mapping addRelationshipMappingWithSourceKeyPath:@"something" mapping:relatedMapping];
RKRelationshipMapping *relationshipMapping = [mapping propertyMappingsByDestinationKeyPath][@"SOMETHING"];
expect(relationshipMapping).notTo.beNil();
expect(relationshipMapping.sourceKeyPath).to.equal(@"something");
expect(relationshipMapping.destinationKeyPath).to.equal(@"SOMETHING");
}
- (void)testTransformationOfAttributeKeyPaths
{
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
[mapping setSourceToDestinationKeyTransformationBlock:^NSString *(RKObjectMapping *mapping, NSString *sourceKey) {
return [sourceKey capitalizedString];
}];
[mapping addAttributeMappingsFromArray:@[ @"user.comments" ]];
NSArray *expectedNames = @[ @"User.Comments" ];
expect([mapping.propertyMappingsByDestinationKeyPath allKeys]).to.equal(expectedNames);
}
- (void)testDefaultSourceToDestinationKeyTransformationBlock
{
[RKObjectMapping setDefaultSourceToDestinationKeyTransformationBlock:^NSString *(RKObjectMapping *mapping, NSString *sourceKey) {
return [sourceKey capitalizedString];
}];
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
[mapping addAttributeMappingsFromArray:@[ @"user.comments" ]];
NSArray *expectedNames = @[ @"User.Comments" ];
expect([mapping.propertyMappingsByDestinationKeyPath allKeys]).to.equal(expectedNames);
}
- (void)testBreakageOfRecursiveInverseCyclicGraphs
{
RKObjectMapping *parentMapping = [RKObjectMapping mappingForClass:[NSObject class]];
[parentMapping addAttributeMappingsFromDictionary:@{ @"first_name": @"firstName", @"last_name": @"lastName" }];
RKObjectMapping *childMapping = [RKObjectMapping mappingForClass:[NSObject class]];
[childMapping addAttributeMappingsFromDictionary:@{ @"first_name": @"firstName", @"last_name": @"lastName" }];
[parentMapping addRelationshipMappingWithSourceKeyPath:@"children" mapping:childMapping];
[childMapping addRelationshipMappingWithSourceKeyPath:@"parents" mapping:parentMapping];
RKObjectMapping *inverseMapping = [parentMapping inverseMapping];
expect([inverseMapping propertyMappingsBySourceKeyPath][@"firstName"]).notTo.beNil();
expect([inverseMapping propertyMappingsBySourceKeyPath][@"lastName"]).notTo.beNil();
expect([inverseMapping propertyMappingsBySourceKeyPath][@"children"]).notTo.beNil();
}
- (void)testInverseMappingWithNilDestinationKeyPathForAttributeMapping
{
// Map @"Blake" to RKTestUser with name = @"Blake"
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[RKTestUser class]];
[mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:nil toKeyPath:@"name"]];
RKObjectMapping *inverseMapping = [mapping inverseMapping];
RKTestUser *user = [RKTestUser new];
user.name = @"Blake";
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
RKMappingOperation *operation = [[RKMappingOperation alloc] initWithSourceObject:user destinationObject:dictionary mapping:inverseMapping];
RKObjectMappingOperationDataSource *dataSource = [RKObjectMappingOperationDataSource new];
operation.dataSource = dataSource;
[operation start];
expect(operation.destinationObject).to.equal(@{ @"Blake": @{} });
}
@end