Add support for testing the mapping used to map a nested relationship in RKMappingTest. closes #802

This commit is contained in:
Blake Watters
2012-06-08 11:25:02 -04:00
parent f18f9337f3
commit 517deb6fa2
4 changed files with 96 additions and 18 deletions

View File

@@ -99,6 +99,17 @@
*/
- (void)expectMappingFromKeyPath:(NSString *)sourceKeyPath toKeyPath:(NSString *)destinationKeyPath passingTest:(BOOL (^)(RKObjectAttributeMapping *mapping, id value))evaluationBlock;
/**
Creates and adds an expectation that a key path on the source object will be mapped to a new
key path on the destination object using the given object mapping.
@param sourceKeyPath A key path on the sourceObject that should be mapped from.
@param destinationKeyPath A key path on the destinationObject that should be mapped to.
@param mapping An object mapping that should be used for mapping the source key path.
@see RKObjectMappingTestExpectation
*/
- (void)expectMappingFromKeyPath:(NSString *)sourceKeyPath toKeyPath:(NSString *)destinationKeyPath usingMapping:(RKObjectMappingDefinition *)mapping;
/**
Adds an expectation to the receiver to be evaluated during verification.

View File

@@ -156,6 +156,11 @@ BOOL RKObjectIsValueEqualToValue(id sourceValue, id destinationValue);
[self addExpectation:[RKMappingTestExpectation expectationWithSourceKeyPath:sourceKeyPath destinationKeyPath:destinationKeyPath evaluationBlock:evaluationBlock]];
}
- (void)expectMappingFromKeyPath:(NSString *)sourceKeyPath toKeyPath:(NSString *)destinationKeyPath usingMapping:(RKObjectMappingDefinition *)mapping
{
[self addExpectation:[RKMappingTestExpectation expectationWithSourceKeyPath:sourceKeyPath destinationKeyPath:destinationKeyPath mapping:mapping]];
}
- (RKMappingTestEvent *)eventMatchingKeyPathsForExpectation:(RKMappingTestExpectation *)expectation
{
for (RKMappingTestEvent *event in self.events) {
@@ -167,18 +172,48 @@ BOOL RKObjectIsValueEqualToValue(id sourceValue, id destinationValue);
return nil;
}
- (BOOL)event:(RKMappingTestEvent *)event satisfiesExpectation:(RKMappingTestExpectation *)expectation
- (BOOL)event:(RKMappingTestEvent *)event satisfiesExpectation:(RKMappingTestExpectation *)expectation errorMessage:(NSString **)errorMessage
{
BOOL success;
if (expectation.evaluationBlock) {
// Let the expectation block evaluate the match
return expectation.evaluationBlock(event.mapping, event.value);
success = expectation.evaluationBlock(event.mapping, event.value);
if (! success) {
*errorMessage = [NSString stringWithFormat:@"%@: expectation not satisfied: %@, but instead got %@ '%@'",
[self description], expectation, [event.value class], event.value];
}
} else if (expectation.value) {
// Use RestKit comparison magic to match values
return RKObjectIsValueEqualToValue(event.value, expectation.value);
success = RKObjectIsValueEqualToValue(event.value, expectation.value);
if (! success) {
*errorMessage = [NSString stringWithFormat:@"%@: expectation not satisfied: %@, but instead got %@ '%@'",
[self description], expectation, [event.value class], event.value];
}
} else if (expectation.mapping) {
if ([event.mapping isKindOfClass:[RKObjectRelationshipMapping class]]) {
// Check the mapping that was used to map the relationship
RKObjectMappingDefinition *relationshipMapping = [(RKObjectRelationshipMapping *)event.mapping mapping];
success = [relationshipMapping isEqualToMapping:expectation.mapping];
if (! success) {
*errorMessage = [NSString stringWithFormat:@"%@: expectation not satisfied: %@ but was instead mapped using: %@",
[self description], expectation, relationshipMapping];
}
} else {
*errorMessage = [NSString stringWithFormat:@"%@: expectation not satisfied: %@, expected an RKObjectRelationshipMapping but instead got a %@",
[self description], expectation, [expectation.mapping class]];
// Error message here that a relationship was not mapped!!!
return NO;
}
} else {
// We only wanted to know that a mapping occured between the keyPaths
success = YES;
}
// We only wanted to know that a mapping occured between the keyPaths
return YES;
return success;
}
- (void)performMapping
@@ -196,8 +231,8 @@ BOOL RKObjectIsValueEqualToValue(id sourceValue, id destinationValue);
mappingOperation.delegate = self;
BOOL success = [mappingOperation performMapping:&error];
if (! success) {
[NSException raise:NSInternalInconsistencyException format:@"%@: failure when mapping from %@ to %@ with mapping %@",
[self description], self.sourceObject, self.destinationObject, self.mapping];
[NSException raise:NSInternalInconsistencyException format:@"%p: failed with error: %@\n%@ during mapping from %@ to %@ with mapping %@",
self, error, [self description], self.sourceObject, self.destinationObject, self.mapping];
}
self.performedMapping = YES;
@@ -209,9 +244,9 @@ BOOL RKObjectIsValueEqualToValue(id sourceValue, id destinationValue);
RKMappingTestEvent *event = [self eventMatchingKeyPathsForExpectation:expectation];
if (event) {
// Found a matching event, check if it satisfies the expectation
if (! [self event:event satisfiesExpectation:expectation]) {
[NSException raise:NSInternalInconsistencyException format:@"%@: expectation not satisfied: %@, but instead got %@ '%@'",
[self description], expectation, [event.value class], event.value];
NSString *errorMessage = nil;
if (! [self event:event satisfiesExpectation:expectation errorMessage:&errorMessage]) {
[NSException raise:NSInternalInconsistencyException format:errorMessage];
}
} else {
// No match

View File

@@ -6,7 +6,7 @@
// Copyright (c) 2009-2012 RestKit. All rights reserved.
//
#import "RKObjectAttributeMapping.h"
@class RKObjectMappingDefinition, RKObjectAttributeMapping;
/**
An RKMappingTestExpectation defines an expected mapping event that should
@@ -26,7 +26,7 @@
@param sourceKeyPath A key path on the source object that should be mapped.
@param destinationKeyPath A key path on the destination object that should be mapped onto.
@return An expectation specifying that sourceKeyPath should be mapped to destionationKeyPath.
@return An expectation specifying that sourceKeyPath should be mapped to destinationKeyPath.
*/
+ (RKMappingTestExpectation *)expectationWithSourceKeyPath:(NSString *)sourceKeyPath destinationKeyPath:(NSString *)destinationKeyPath;
@@ -37,7 +37,7 @@
@param sourceKeyPath A key path on the source object that should be mapped.
@param destinationKeyPath A key path on the destination object that should be mapped onto.
@param value The value that is expected to be assigned to the destination object at destinationKeyPath.
@return An expectation specifying that sourceKeyPath should be mapped to destionationKeyPath with value.
@return An expectation specifying that sourceKeyPath should be mapped to destinationKeyPath with value.
*/
+ (RKMappingTestExpectation *)expectationWithSourceKeyPath:(NSString *)sourceKeyPath destinationKeyPath:(NSString *)destinationKeyPath value:(id)value;
@@ -49,10 +49,21 @@
@param sourceKeyPath A key path on the source object that should be mapped.
@param destinationKeyPath A key path on the destination object that should be mapped onto.
@param evaluationBlock A block with which to evaluate the success of the mapping.
@return An expectation specifying that sourceKeyPath should be mapped to destionationKeyPath with value.
@return An expectation specifying that sourceKeyPath should be mapped to destinationKeyPath with value.
*/
+ (RKMappingTestExpectation *)expectationWithSourceKeyPath:(NSString *)sourceKeyPath destinationKeyPath:(NSString *)destinationKeyPath evaluationBlock:(BOOL (^)(RKObjectAttributeMapping *mapping, id value))evaluationBlock;
/**
Creates and returns a new expectation specifying that a key path in a source object should be
mapped to another key path on a destinaton object using a specific object mapping for the relationship.
@param sourceKeyPath A key path on the source object that should be mapped.
@param destinationKeyPath A key path on the destination object that should be mapped onto.
@param mapping An object mapping that is expected to be used for mapping the nested relationship.
@return An expectation specifying that sourceKeyPath should be mapped to destinationKeyPath using a specific object mapping.
*/
+ (RKMappingTestExpectation *)expectationWithSourceKeyPath:(NSString *)sourceKeyPath destinationKeyPath:(NSString *)destinationKeyPath mapping:(RKObjectMappingDefinition *)mapping;
///-----------------------------------------------------------------------------
/// @name Expectation Values
///-----------------------------------------------------------------------------
@@ -77,6 +88,11 @@
*/
@property (nonatomic, copy, readonly) BOOL (^evaluationBlock)(RKObjectAttributeMapping *mapping, id value);
/**
Returns the expected object mapping to be used for mapping a nested relationship.
*/
@property (nonatomic, strong, readonly) RKObjectMappingDefinition *mapping;
/**
Returns a string summary of the expected keyPath mapping within the expectation

View File

@@ -7,21 +7,24 @@
//
#import "RKMappingTestExpectation.h"
#import "RKObjectAttributeMapping.h"
@interface RKMappingTestExpectation ()
@property (nonatomic, copy, readwrite) NSString *sourceKeyPath;
@property (nonatomic, copy, readwrite) NSString *destinationKeyPath;
@property (nonatomic, strong, readwrite) id value;
@property (nonatomic, copy, readwrite) BOOL (^evaluationBlock)(RKObjectAttributeMapping *mapping, id value);
@property (nonatomic, strong, readwrite) RKObjectMappingDefinition *mapping;
@end
@implementation RKMappingTestExpectation
@synthesize sourceKeyPath;
@synthesize destinationKeyPath;
@synthesize value;
@synthesize evaluationBlock;
@synthesize sourceKeyPath = _sourceKeyPath;
@synthesize destinationKeyPath = _destinationKeyPath;
@synthesize value = _value;
@synthesize evaluationBlock = _evaluationBlock;
@synthesize mapping = _mapping;
+ (RKMappingTestExpectation *)expectationWithSourceKeyPath:(NSString *)sourceKeyPath destinationKeyPath:(NSString *)destinationKeyPath
{
@@ -52,6 +55,16 @@
return expectation;
}
+ (RKMappingTestExpectation *)expectationWithSourceKeyPath:(NSString *)sourceKeyPath destinationKeyPath:(NSString *)destinationKeyPath mapping:(RKObjectMappingDefinition *)mapping
{
RKMappingTestExpectation *expectation = [self new];
expectation.sourceKeyPath = sourceKeyPath;
expectation.destinationKeyPath = destinationKeyPath;
expectation.mapping = mapping;
return expectation;
}
- (NSString *)mappingDescription
{
return [NSString stringWithFormat:@"expected sourceKeyPath '%@' to map to destinationKeyPath '%@'",
@@ -66,6 +79,9 @@
} else if (self.evaluationBlock) {
return [NSString stringWithFormat:@"expected sourceKeyPath '%@' to map to destinationKeyPath '%@' satisfying evaluation block",
self.sourceKeyPath, self.destinationKeyPath];
} else if (self.mapping) {
return [NSString stringWithFormat:@"expected sourceKeyPath '%@' to map to destinationKeyPath '%@' using mapping: %@",
self.sourceKeyPath, self.destinationKeyPath, self.mapping];
}
return [self mappingDescription];