mirror of
https://github.com/zhigang1992/RestKit.git
synced 2026-04-02 22:42:45 +08:00
809 lines
35 KiB
Objective-C
809 lines
35 KiB
Objective-C
//
|
|
// RKObjectLoaderTest.m
|
|
// RestKit
|
|
//
|
|
// Created by Blake Watters on 4/27/11.
|
|
// Copyright (c) 2009-2012 RestKit. All rights reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
|
|
#import "RKTestEnvironment.h"
|
|
#import "RKObjectMappingProvider.h"
|
|
#import "RKErrorMessage.h"
|
|
#import "RKJSONParserJSONKit.h"
|
|
|
|
// Models
|
|
#import "RKObjectLoaderTestResultModel.h"
|
|
|
|
@interface RKTestComplexUser : NSObject {
|
|
NSNumber *_userID;
|
|
NSString *_firstname;
|
|
NSString *_lastname;
|
|
NSString *_email;
|
|
NSString *_phone;
|
|
}
|
|
|
|
@property (nonatomic, retain) NSNumber *userID;
|
|
@property (nonatomic, retain) NSString *firstname;
|
|
@property (nonatomic, retain) NSString *lastname;
|
|
@property (nonatomic, retain) NSString *email;
|
|
@property (nonatomic, retain) NSString *phone;
|
|
|
|
@end
|
|
|
|
@implementation RKTestComplexUser
|
|
|
|
@synthesize userID = _userID;
|
|
@synthesize firstname = _firstname;
|
|
@synthesize lastname = _lastname;
|
|
@synthesize phone = _phone;
|
|
@synthesize email = _email;
|
|
|
|
- (void)willSendWithObjectLoader:(RKObjectLoader *)objectLoader
|
|
{
|
|
return;
|
|
}
|
|
|
|
@end
|
|
|
|
@interface RKTestResponseLoaderWithWillMapData : RKTestResponseLoader {
|
|
id _mappableData;
|
|
}
|
|
|
|
@property (nonatomic, readonly) id mappableData;
|
|
|
|
@end
|
|
|
|
@implementation RKTestResponseLoaderWithWillMapData
|
|
|
|
@synthesize mappableData = _mappableData;
|
|
|
|
- (void)dealloc
|
|
{
|
|
[_mappableData release];
|
|
[super dealloc];
|
|
}
|
|
|
|
- (void)objectLoader:(RKObjectLoader *)loader willMapData:(inout id *)mappableData
|
|
{
|
|
[*mappableData setValue:@"monkey!" forKey:@"newKey"];
|
|
_mappableData = [*mappableData retain];
|
|
}
|
|
|
|
@end
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
@interface RKObjectLoaderTest : RKTestCase {
|
|
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation RKObjectLoaderTest
|
|
|
|
- (void)setUp
|
|
{
|
|
[RKTestFactory setUp];
|
|
}
|
|
|
|
- (void)tearDown
|
|
{
|
|
[RKTestFactory tearDown];
|
|
}
|
|
|
|
- (RKObjectMappingProvider *)providerForComplexUser
|
|
{
|
|
RKObjectMappingProvider *provider = [[RKObjectMappingProvider new] autorelease];
|
|
RKObjectMapping *userMapping = [RKObjectMapping mappingForClass:[RKTestComplexUser class]];
|
|
[userMapping addAttributeMapping:[RKAttributeMapping mappingFromKeyPath:@"firstname" toKeyPath:@"firstname"]];
|
|
[provider setMapping:userMapping forKeyPath:@"data.STUser"];
|
|
return provider;
|
|
}
|
|
|
|
- (RKObjectMappingProvider *)errorMappingProvider
|
|
{
|
|
RKObjectMappingProvider *provider = [[RKObjectMappingProvider new] autorelease];
|
|
RKObjectMapping *errorMapping = [RKObjectMapping mappingForClass:[RKErrorMessage class]];
|
|
[errorMapping addAttributeMapping:[RKAttributeMapping mappingFromKeyPath:@"" toKeyPath:@"errorMessage"]];
|
|
errorMapping.rootKeyPath = @"errors";
|
|
provider.errorMapping = errorMapping;
|
|
return provider;
|
|
}
|
|
|
|
- (void)testShouldHandleTheErrorCaseAppropriately
|
|
{
|
|
RKObjectManager *objectManager = [RKTestFactory objectManager];
|
|
objectManager.mappingProvider = [self errorMappingProvider];
|
|
|
|
RKTestResponseLoader *responseLoader = [RKTestResponseLoader responseLoader];
|
|
RKObjectLoader *objectLoader = [objectManager loaderWithResourcePath:@"/errors.json"];
|
|
objectLoader.delegate = responseLoader;
|
|
objectLoader.method = RKRequestMethodGET;
|
|
[objectLoader sendAsynchronously];
|
|
[responseLoader waitForResponse];
|
|
|
|
assertThat(responseLoader.error, isNot(nilValue()));
|
|
assertThat([responseLoader.error localizedDescription], is(equalTo(@"error1, error2")));
|
|
|
|
NSArray *objects = [[responseLoader.error userInfo] objectForKey:RKObjectMapperErrorObjectsKey];
|
|
RKErrorMessage *error1 = [objects objectAtIndex:0];
|
|
RKErrorMessage *error2 = [objects lastObject];
|
|
|
|
assertThat(error1.errorMessage, is(equalTo(@"error1")));
|
|
assertThat(error2.errorMessage, is(equalTo(@"error2")));
|
|
}
|
|
|
|
- (void)testShouldNotCrashWhenLoadingAnErrorResponseWithAnUnmappableMIMEType
|
|
{
|
|
RKObjectManager *objectManager = [RKTestFactory objectManager];
|
|
RKTestResponseLoader *loader = [RKTestResponseLoader responseLoader];
|
|
[objectManager loadObjectsAtResourcePath:@"/404" delegate:loader];
|
|
[loader waitForResponse];
|
|
assertThatBool(loader.loadedUnexpectedResponse, is(equalToBool(YES)));
|
|
}
|
|
|
|
#pragma mark - Complex JSON
|
|
|
|
- (void)testShouldLoadAComplexUserObjectWithTargetObject
|
|
{
|
|
RKTestComplexUser *user = [[RKTestComplexUser new] autorelease];
|
|
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[RKTestFactory baseURL]];
|
|
RKTestResponseLoader *responseLoader = [RKTestResponseLoader responseLoader];
|
|
RKObjectLoader *objectLoader = [objectManager loaderWithResourcePath:@"/JSON/ComplexNestedUser.json"];
|
|
objectLoader.delegate = responseLoader;
|
|
NSString *authString = [NSString stringWithFormat:@"TRUEREST username=%@&password=%@&apikey=123456&class=iphone", @"username", @"password"];
|
|
[objectLoader.URLRequest addValue:authString forHTTPHeaderField:@"Authorization"];
|
|
objectLoader.method = RKRequestMethodGET;
|
|
objectLoader.targetObject = user;
|
|
objectLoader.mappingProvider = [self providerForComplexUser];
|
|
|
|
[objectLoader sendAsynchronously];
|
|
[responseLoader waitForResponse];
|
|
|
|
assertThat(user.firstname, is(equalTo(@"Diego")));
|
|
}
|
|
|
|
- (void)testShouldLoadAComplexUserObjectWithoutTargetObject
|
|
{
|
|
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[RKTestFactory baseURL]];
|
|
RKTestResponseLoader *responseLoader = [RKTestResponseLoader responseLoader];
|
|
RKObjectLoader *objectLoader = [objectManager loaderWithResourcePath:@"/JSON/ComplexNestedUser.json"];
|
|
objectLoader.delegate = responseLoader;
|
|
objectLoader.method = RKRequestMethodGET;
|
|
objectLoader.mappingProvider = [self providerForComplexUser];
|
|
|
|
[objectLoader sendAsynchronously];
|
|
[responseLoader waitForResponse];
|
|
assertThatUnsignedInteger([responseLoader.objects count], is(equalToInt(1)));
|
|
RKTestComplexUser *user = [responseLoader.objects lastObject];
|
|
|
|
assertThat(user.firstname, is(equalTo(@"Diego")));
|
|
}
|
|
|
|
- (void)testShouldLoadAComplexUserObjectUsingRegisteredKeyPath
|
|
{
|
|
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[RKTestFactory baseURL]];
|
|
RKTestResponseLoader *responseLoader = [RKTestResponseLoader responseLoader];
|
|
RKObjectLoader *objectLoader = [objectManager loaderWithResourcePath:@"/JSON/ComplexNestedUser.json"];
|
|
objectLoader.delegate = responseLoader;
|
|
objectLoader.method = RKRequestMethodGET;
|
|
objectLoader.mappingProvider = [self providerForComplexUser];
|
|
[objectLoader sendAsynchronously];
|
|
[responseLoader waitForResponse];
|
|
assertThatUnsignedInteger([responseLoader.objects count], is(equalToInt(1)));
|
|
RKTestComplexUser *user = [responseLoader.objects lastObject];
|
|
|
|
assertThat(user.firstname, is(equalTo(@"Diego")));
|
|
}
|
|
|
|
#pragma mark - willSendWithObjectLoader:
|
|
|
|
- (void)testShouldInvokeWillSendWithObjectLoaderOnSend
|
|
{
|
|
RKObjectManager *objectManager = [RKTestFactory objectManager];
|
|
RKTestComplexUser *user = [[RKTestComplexUser new] autorelease];
|
|
id mockObject = [OCMockObject partialMockForObject:user];
|
|
|
|
// Explicitly init so we don't get a managed object loader...
|
|
RKTestResponseLoader *responseLoader = [RKTestResponseLoader responseLoader];
|
|
RKObjectLoader *objectLoader = [[RKObjectLoader alloc] initWithURL:[objectManager.baseURL URLByAppendingResourcePath:@"/200"] mappingProvider:[self providerForComplexUser]];
|
|
objectLoader.configurationDelegate = objectManager;
|
|
objectLoader.sourceObject = mockObject;
|
|
objectLoader.delegate = responseLoader;
|
|
[[mockObject expect] willSendWithObjectLoader:objectLoader];
|
|
[objectLoader send];
|
|
[responseLoader waitForResponse];
|
|
[mockObject verify];
|
|
}
|
|
|
|
- (void)testShouldInvokeWillSendWithObjectLoaderOnSendAsynchronously
|
|
{
|
|
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[RKTestFactory baseURL]];
|
|
[objectManager setMappingProvider:[self providerForComplexUser]];
|
|
RKTestComplexUser *user = [[RKTestComplexUser new] autorelease];
|
|
id mockObject = [OCMockObject partialMockForObject:user];
|
|
|
|
// Explicitly init so we don't get a managed object loader...
|
|
RKTestResponseLoader *responseLoader = [RKTestResponseLoader responseLoader];
|
|
RKObjectLoader *objectLoader = [RKObjectLoader loaderWithURL:[objectManager.baseURL URLByAppendingResourcePath:@"/200"] mappingProvider:objectManager.mappingProvider];
|
|
objectLoader.delegate = responseLoader;
|
|
objectLoader.sourceObject = mockObject;
|
|
[[mockObject expect] willSendWithObjectLoader:objectLoader];
|
|
[objectLoader sendAsynchronously];
|
|
[responseLoader waitForResponse];
|
|
[mockObject verify];
|
|
}
|
|
|
|
- (void)testShouldInvokeWillSendWithObjectLoaderOnSendSynchronously
|
|
{
|
|
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[RKTestFactory baseURL]];
|
|
[objectManager setMappingProvider:[self providerForComplexUser]];
|
|
RKTestComplexUser *user = [[RKTestComplexUser new] autorelease];
|
|
id mockObject = [OCMockObject partialMockForObject:user];
|
|
|
|
// Explicitly init so we don't get a managed object loader...
|
|
RKObjectLoader *objectLoader = [RKObjectLoader loaderWithURL:[objectManager.baseURL URLByAppendingResourcePath:@"/200"] mappingProvider:objectManager.mappingProvider];
|
|
objectLoader.sourceObject = mockObject;
|
|
[[mockObject expect] willSendWithObjectLoader:objectLoader];
|
|
[objectLoader sendSynchronously];
|
|
[mockObject verify];
|
|
}
|
|
|
|
- (void)testShouldLoadResultsNestedAtAKeyPath
|
|
{
|
|
RKObjectManager *objectManager = [RKTestFactory objectManager];
|
|
RKObjectMapping *objectMapping = [RKObjectMapping mappingForClass:[RKObjectLoaderTestResultModel class]];
|
|
[objectMapping mapKeyPath:@"id" toAttribute:@"ID"];
|
|
[objectMapping mapKeyPath:@"ends_at" toAttribute:@"endsAt"];
|
|
[objectMapping mapKeyPath:@"photo_url" toAttribute:@"photoURL"];
|
|
[objectManager.mappingProvider setMapping:objectMapping forKeyPath:@"results"];
|
|
RKTestResponseLoader *loader = [RKTestResponseLoader responseLoader];
|
|
[objectManager loadObjectsAtResourcePath:@"/JSON/ArrayOfResults.json" delegate:loader];
|
|
[loader waitForResponse];
|
|
assertThat([loader objects], hasCountOf(2));
|
|
assertThat([[[loader objects] objectAtIndex:0] ID], is(equalToInt(226)));
|
|
assertThat([[[loader objects] objectAtIndex:0] photoURL], is(equalTo(@"1308262872.jpg")));
|
|
assertThat([[[loader objects] objectAtIndex:1] ID], is(equalToInt(235)));
|
|
assertThat([[[loader objects] objectAtIndex:1] photoURL], is(equalTo(@"1308634984.jpg")));
|
|
}
|
|
|
|
- (void)testShouldAllowMutationOfTheParsedDataInWillMapData
|
|
{
|
|
RKTestResponseLoaderWithWillMapData *loader = (RKTestResponseLoaderWithWillMapData *)[RKTestResponseLoaderWithWillMapData responseLoader];
|
|
RKObjectManager *manager = [RKTestFactory objectManager];
|
|
[manager loadObjectsAtResourcePath:@"/JSON/humans/1.json" delegate:loader];
|
|
[loader waitForResponse];
|
|
assertThat([loader.mappableData valueForKey:@"newKey"], is(equalTo(@"monkey!")));
|
|
}
|
|
|
|
- (void)testShouldAllowYouToPostAnObjectAndHandleAnEmpty204Response
|
|
{
|
|
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[RKTestComplexUser class]];
|
|
[mapping mapAttributes:@"firstname", @"lastname", @"email", nil];
|
|
RKObjectMapping *serializationMapping = [mapping inverseMapping];
|
|
|
|
RKObjectManager *objectManager = [RKTestFactory objectManager];
|
|
[objectManager.router.routeSet addRoute:[RKRoute routeWithClass:[RKTestComplexUser class] resourcePathPattern:@"/204"method:RKRequestMethodAny]];
|
|
[objectManager.mappingProvider setSerializationMapping:serializationMapping forClass:[RKTestComplexUser class]];
|
|
|
|
RKTestComplexUser *user = [[RKTestComplexUser new] autorelease];
|
|
user.firstname = @"Blake";
|
|
user.lastname = @"Watters";
|
|
user.email = @"blake@restkit.org";
|
|
|
|
RKTestResponseLoader *responseLoader = [RKTestResponseLoader responseLoader];
|
|
RKObjectLoader *loader = [objectManager loaderForObject:user method:RKRequestMethodPOST];
|
|
loader.delegate = responseLoader;
|
|
loader.objectMapping = mapping;
|
|
[loader send];
|
|
[responseLoader waitForResponse];
|
|
assertThatBool([responseLoader wasSuccessful], is(equalToBool(YES)));
|
|
assertThat(user.email, is(equalTo(@"blake@restkit.org")));
|
|
}
|
|
|
|
- (void)testShouldAllowYouToPOSTAnObjectAndMapBackNonNestedContent
|
|
{
|
|
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[RKTestComplexUser class]];
|
|
[mapping mapAttributes:@"firstname", @"lastname", @"email", nil];
|
|
RKObjectMapping *serializationMapping = [mapping inverseMapping];
|
|
|
|
RKObjectManager *objectManager = [RKTestFactory objectManager];
|
|
[objectManager.router.routeSet addRoute:[RKRoute routeWithClass:[RKTestComplexUser class] resourcePathPattern:@"/notNestedUser" method:RKRequestMethodAny]];
|
|
[objectManager.mappingProvider setSerializationMapping:serializationMapping forClass:[RKTestComplexUser class]];
|
|
|
|
RKTestComplexUser *user = [[RKTestComplexUser new] autorelease];
|
|
user.firstname = @"Blake";
|
|
user.lastname = @"Watters";
|
|
user.email = @"blake@restkit.org";
|
|
|
|
RKTestResponseLoader *responseLoader = [RKTestResponseLoader responseLoader];
|
|
RKObjectLoader *loader = [objectManager loaderForObject:user method:RKRequestMethodPOST];
|
|
loader.delegate = responseLoader;
|
|
loader.objectMapping = mapping;
|
|
[loader send];
|
|
[responseLoader waitForResponse];
|
|
assertThatBool([responseLoader wasSuccessful], is(equalToBool(YES)));
|
|
assertThat(user.email, is(equalTo(@"changed")));
|
|
}
|
|
|
|
- (void)testShouldMapContentWithoutAMIMEType
|
|
{
|
|
// TODO: Not sure that this is even worth it. Unable to get the Sinatra server to produce such a response
|
|
return;
|
|
RKLogConfigureByName("RestKit/Network", RKLogLevelTrace);
|
|
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[RKTestComplexUser class]];
|
|
[mapping mapAttributes:@"firstname", @"lastname", @"email", nil];
|
|
RKObjectMapping *serializationMapping = [mapping inverseMapping];
|
|
|
|
RKObjectManager *objectManager = [RKTestFactory objectManager];
|
|
[[RKParserRegistry sharedRegistry] setParserClass:[RKJSONParserJSONKit class] forMIMEType:@"text/html"];
|
|
[objectManager.router.routeSet addRoute:[RKRoute routeWithClass:[RKTestComplexUser class] resourcePathPattern:@"/noMIME" method:RKRequestMethodAny]];
|
|
[objectManager.mappingProvider setSerializationMapping:serializationMapping forClass:[RKTestComplexUser class]];
|
|
|
|
RKTestComplexUser *user = [[RKTestComplexUser new] autorelease];
|
|
user.firstname = @"Blake";
|
|
user.lastname = @"Watters";
|
|
user.email = @"blake@restkit.org";
|
|
|
|
RKTestResponseLoader *responseLoader = [RKTestResponseLoader responseLoader];
|
|
RKObjectLoader *loader = [objectManager loaderForObject:user method:RKRequestMethodPOST];
|
|
loader.delegate = responseLoader;
|
|
loader.objectMapping = mapping;
|
|
[loader send];
|
|
[responseLoader waitForResponse];
|
|
assertThatBool([responseLoader wasSuccessful], is(equalToBool(YES)));
|
|
assertThat(user.email, is(equalTo(@"changed")));
|
|
}
|
|
|
|
- (void)testShouldAllowYouToPOSTAnObjectOfOneTypeAndGetBackAnother
|
|
{
|
|
RKObjectMapping *sourceMapping = [RKObjectMapping mappingForClass:[RKTestComplexUser class]];
|
|
[sourceMapping mapAttributes:@"firstname", @"lastname", @"email", nil];
|
|
RKObjectMapping *serializationMapping = [sourceMapping inverseMapping];
|
|
|
|
RKObjectMapping *targetMapping = [RKObjectMapping mappingForClass:[RKObjectLoaderTestResultModel class]];
|
|
[targetMapping mapAttributes:@"ID", nil];
|
|
|
|
RKObjectManager *objectManager = [RKTestFactory objectManager];
|
|
[objectManager.router.routeSet addRoute:[RKRoute routeWithClass:[RKTestComplexUser class] resourcePathPattern:@"/notNestedUser" method:RKRequestMethodAny]];
|
|
[objectManager.mappingProvider setSerializationMapping:serializationMapping forClass:[RKTestComplexUser class]];
|
|
|
|
RKTestComplexUser *user = [[RKTestComplexUser new] autorelease];
|
|
user.firstname = @"Blake";
|
|
user.lastname = @"Watters";
|
|
user.email = @"blake@restkit.org";
|
|
|
|
RKTestResponseLoader *responseLoader = [RKTestResponseLoader responseLoader];
|
|
RKObjectLoader *loader = [objectManager loaderForObject:user method:RKRequestMethodPOST];
|
|
loader.delegate = responseLoader;
|
|
loader.sourceObject = user;
|
|
loader.targetObject = nil;
|
|
loader.objectMapping = targetMapping;
|
|
[loader send];
|
|
[responseLoader waitForResponse];
|
|
assertThatBool([responseLoader wasSuccessful], is(equalToBool(YES)));
|
|
|
|
// Our original object should not have changed
|
|
assertThat(user.email, is(equalTo(@"blake@restkit.org")));
|
|
|
|
// And we should have a new one
|
|
RKObjectLoaderTestResultModel *newObject = [[responseLoader objects] lastObject];
|
|
assertThat(newObject, is(instanceOf([RKObjectLoaderTestResultModel class])));
|
|
assertThat(newObject.ID, is(equalToInt(31337)));
|
|
}
|
|
|
|
- (void)testShouldAllowYouToPOSTAnObjectOfOneTypeAndGetBackAnotherViaURLConfiguration
|
|
{
|
|
RKObjectMapping *sourceMapping = [RKObjectMapping mappingForClass:[RKTestComplexUser class]];
|
|
[sourceMapping mapAttributes:@"firstname", @"lastname", @"email", nil];
|
|
RKObjectMapping *serializationMapping = [sourceMapping inverseMapping];
|
|
|
|
RKObjectMapping *targetMapping = [RKObjectMapping mappingForClass:[RKObjectLoaderTestResultModel class]];
|
|
[targetMapping mapAttributes:@"ID", nil];
|
|
|
|
RKObjectManager *objectManager = [RKTestFactory objectManager];
|
|
[objectManager.router.routeSet addRoute:[RKRoute routeWithClass:[RKTestComplexUser class] resourcePathPattern:@"/notNestedUser" method:RKRequestMethodAny]];
|
|
[objectManager.mappingProvider setSerializationMapping:serializationMapping forClass:[RKTestComplexUser class]];
|
|
[objectManager.mappingProvider setObjectMapping:targetMapping forResourcePathPattern:@"/notNestedUser"];
|
|
|
|
RKTestComplexUser *user = [[RKTestComplexUser new] autorelease];
|
|
user.firstname = @"Blake";
|
|
user.lastname = @"Watters";
|
|
user.email = @"blake@restkit.org";
|
|
|
|
RKTestResponseLoader *responseLoader = [RKTestResponseLoader responseLoader];
|
|
RKObjectLoader *loader = [objectManager loaderForObject:user method:RKRequestMethodPOST];
|
|
loader.delegate = responseLoader;
|
|
loader.sourceObject = user;
|
|
loader.targetObject = nil;
|
|
[loader send];
|
|
[responseLoader waitForResponse];
|
|
assertThatBool([responseLoader wasSuccessful], is(equalToBool(YES)));
|
|
|
|
// Our original object should not have changed
|
|
assertThat(user.email, is(equalTo(@"blake@restkit.org")));
|
|
|
|
// And we should have a new one
|
|
RKObjectLoaderTestResultModel *newObject = [[responseLoader objects] lastObject];
|
|
assertThat(newObject, is(instanceOf([RKObjectLoaderTestResultModel class])));
|
|
assertThat(newObject.ID, is(equalToInt(31337)));
|
|
}
|
|
|
|
// TODO: Should live in a different file...
|
|
- (void)testShouldAllowYouToPOSTAnObjectAndMapBackNonNestedContentViapostObject
|
|
{
|
|
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[RKTestComplexUser class]];
|
|
[mapping mapAttributes:@"firstname", @"lastname", @"email", nil];
|
|
RKObjectMapping *serializationMapping = [mapping inverseMapping];
|
|
|
|
RKObjectManager *objectManager = [RKTestFactory objectManager];
|
|
[objectManager.router.routeSet addRoute:[RKRoute routeWithClass:[RKTestComplexUser class] resourcePathPattern:@"/notNestedUser" method:RKRequestMethodAny]];
|
|
[objectManager.mappingProvider setSerializationMapping:serializationMapping forClass:[RKTestComplexUser class]];
|
|
|
|
RKTestComplexUser *user = [[RKTestComplexUser new] autorelease];
|
|
user.firstname = @"Blake";
|
|
user.lastname = @"Watters";
|
|
user.email = @"blake@restkit.org";
|
|
|
|
// NOTE: The postObject: should infer the target object from sourceObject and the mapping class
|
|
RKTestResponseLoader *responseLoader = [RKTestResponseLoader responseLoader];
|
|
[objectManager postObject:user usingBlock:^(RKObjectLoader *loader) {
|
|
loader.delegate = responseLoader;
|
|
loader.objectMapping = mapping;
|
|
}];
|
|
[responseLoader waitForResponse];
|
|
assertThatBool([responseLoader wasSuccessful], is(equalToBool(YES)));
|
|
assertThat(user.email, is(equalTo(@"changed")));
|
|
}
|
|
|
|
- (void)testShouldRespectTheRootKeyPathWhenConstructingATemporaryObjectMappingProvider
|
|
{
|
|
RKObjectMapping *userMapping = [RKObjectMapping mappingForClass:[RKTestComplexUser class]];
|
|
userMapping.rootKeyPath = @"data.STUser";
|
|
[userMapping mapAttributes:@"firstname", nil];
|
|
|
|
RKTestComplexUser *user = [[RKTestComplexUser new] autorelease];
|
|
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[RKTestFactory baseURL]];
|
|
RKTestResponseLoader *responseLoader = [RKTestResponseLoader responseLoader];
|
|
|
|
RKObjectLoader *objectLoader = [objectManager loaderWithResourcePath:@"/JSON/ComplexNestedUser.json"];
|
|
objectLoader.delegate = responseLoader;
|
|
objectLoader.objectMapping = userMapping;
|
|
objectLoader.method = RKRequestMethodGET;
|
|
objectLoader.targetObject = user;
|
|
|
|
[objectLoader sendAsynchronously];
|
|
[responseLoader waitForResponse];
|
|
|
|
assertThat(user.firstname, is(equalTo(@"Diego")));
|
|
}
|
|
|
|
- (void)testShouldDetermineObjectLoaderBasedOnResourcePathPatternWithExactMatch
|
|
{
|
|
RKObjectMapping *userMapping = [RKObjectMapping mappingForClass:[RKTestComplexUser class]];
|
|
userMapping.rootKeyPath = @"data.STUser";
|
|
[userMapping mapAttributes:@"firstname", nil];
|
|
|
|
RKTestComplexUser *user = [[RKTestComplexUser new] autorelease];
|
|
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[RKTestFactory baseURL]];
|
|
RKTestResponseLoader *responseLoader = [RKTestResponseLoader responseLoader];
|
|
RKObjectMappingProvider *mappingProvider = [RKObjectMappingProvider mappingProvider];
|
|
[mappingProvider setObjectMapping:userMapping forResourcePathPattern:@"/JSON/ComplexNestedUser.json"];
|
|
|
|
RKURL *URL = [objectManager.baseURL URLByAppendingResourcePath:@"/JSON/ComplexNestedUser.json"];
|
|
RKObjectLoader *objectLoader = [RKObjectLoader loaderWithURL:URL mappingProvider:mappingProvider];
|
|
objectLoader.delegate = responseLoader;
|
|
objectLoader.method = RKRequestMethodGET;
|
|
objectLoader.targetObject = user;
|
|
|
|
[objectLoader sendAsynchronously];
|
|
[responseLoader waitForResponse];
|
|
|
|
NSLog(@"Response: %@", responseLoader.objects);
|
|
|
|
assertThat(user.firstname, is(equalTo(@"Diego")));
|
|
}
|
|
|
|
- (void)testShouldDetermineObjectLoaderBasedOnResourcePathPatternWithPartialMatch
|
|
{
|
|
RKObjectMapping *userMapping = [RKObjectMapping mappingForClass:[RKTestComplexUser class]];
|
|
userMapping.rootKeyPath = @"data.STUser";
|
|
[userMapping mapAttributes:@"firstname", nil];
|
|
|
|
RKTestComplexUser *user = [[RKTestComplexUser new] autorelease];
|
|
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[RKTestFactory baseURL]];
|
|
RKTestResponseLoader *responseLoader = [RKTestResponseLoader responseLoader];
|
|
RKObjectMappingProvider *mappingProvider = [RKObjectMappingProvider mappingProvider];
|
|
[mappingProvider setObjectMapping:userMapping forResourcePathPattern:@"/JSON/:name\\.json"];
|
|
|
|
RKURL *URL = [objectManager.baseURL URLByAppendingResourcePath:@"/JSON/ComplexNestedUser.json"];
|
|
RKObjectLoader *objectLoader = [RKObjectLoader loaderWithURL:URL mappingProvider:mappingProvider];
|
|
objectLoader.delegate = responseLoader;
|
|
objectLoader.method = RKRequestMethodGET;
|
|
objectLoader.targetObject = user;
|
|
|
|
[objectLoader sendAsynchronously];
|
|
[responseLoader waitForResponse];
|
|
|
|
NSLog(@"Response: %@", responseLoader.objects);
|
|
|
|
assertThat(user.firstname, is(equalTo(@"Diego")));
|
|
}
|
|
|
|
- (void)testShouldReturnSuccessWhenTheStatusCodeIs200AndTheResponseBodyIsEmpty
|
|
{
|
|
RKObjectManager *objectManager = [RKTestFactory objectManager];
|
|
|
|
RKTestComplexUser *user = [[RKTestComplexUser new] autorelease];
|
|
user.firstname = @"Blake";
|
|
user.lastname = @"Watters";
|
|
user.email = @"blake@restkit.org";
|
|
|
|
RKObjectMapping *userMapping = [RKObjectMapping mappingForClass:[RKTestComplexUser class]];
|
|
userMapping.rootKeyPath = @"data.STUser";
|
|
[userMapping mapAttributes:@"firstname", nil];
|
|
RKTestResponseLoader *responseLoader = [RKTestResponseLoader responseLoader];
|
|
RKObjectLoader *objectLoader = [objectManager loaderWithResourcePath:@"/humans/1234"];
|
|
objectLoader.delegate = responseLoader;
|
|
objectLoader.method = RKRequestMethodDELETE;
|
|
objectLoader.objectMapping = userMapping;
|
|
objectLoader.targetObject = user;
|
|
[objectLoader send];
|
|
[responseLoader waitForResponse];
|
|
assertThatBool(responseLoader.wasSuccessful, is(equalToBool(YES)));
|
|
}
|
|
|
|
- (void)testShouldInvokeTheDelegateWithTheTargetObjectWhenTheStatusCodeIs200AndTheResponseBodyIsEmpty
|
|
{
|
|
RKObjectManager *objectManager = [RKTestFactory objectManager];
|
|
|
|
RKTestComplexUser *user = [[RKTestComplexUser new] autorelease];
|
|
user.firstname = @"Blake";
|
|
user.lastname = @"Watters";
|
|
user.email = @"blake@restkit.org";
|
|
|
|
RKObjectMapping *userMapping = [RKObjectMapping mappingForClass:[RKTestComplexUser class]];
|
|
userMapping.rootKeyPath = @"data.STUser";
|
|
[userMapping mapAttributes:@"firstname", nil];
|
|
RKTestResponseLoader *responseLoader = [RKTestResponseLoader responseLoader];
|
|
|
|
RKObjectLoader *objectLoader = [RKObjectLoader loaderWithURL:[objectManager.baseURL URLByAppendingResourcePath:@"/humans/1234"] mappingProvider:objectManager.mappingProvider];
|
|
objectLoader.delegate = responseLoader;
|
|
objectLoader.method = RKRequestMethodDELETE;
|
|
objectLoader.objectMapping = userMapping;
|
|
objectLoader.targetObject = user;
|
|
[objectLoader send];
|
|
[responseLoader waitForResponse];
|
|
assertThat(responseLoader.objects, hasItem(user));
|
|
}
|
|
|
|
- (void)testShouldConsiderTheLoadOfEmptyObjectsWithoutAnyMappableAttributesAsSuccess
|
|
{
|
|
RKObjectManager *objectManager = [RKTestFactory objectManager];
|
|
|
|
RKObjectMapping *userMapping = [RKObjectMapping mappingForClass:[RKTestComplexUser class]];
|
|
[userMapping mapAttributes:@"firstname", nil];
|
|
[objectManager.mappingProvider setMapping:userMapping forKeyPath:@"firstUser"];
|
|
[objectManager.mappingProvider setMapping:userMapping forKeyPath:@"secondUser"];
|
|
|
|
RKTestResponseLoader *responseLoader = [RKTestResponseLoader responseLoader];
|
|
[objectManager loadObjectsAtResourcePath:@"/users/empty" delegate:responseLoader];
|
|
[responseLoader waitForResponse];
|
|
assertThatBool(responseLoader.wasSuccessful, is(equalToBool(YES)));
|
|
}
|
|
|
|
- (void)testShouldInvokeTheDelegateOnSuccessIfTheResponseIsAnEmptyArray
|
|
{
|
|
RKObjectManager *objectManager = [RKTestFactory objectManager];
|
|
RKTestResponseLoader *responseLoader = [RKTestResponseLoader responseLoader];
|
|
responseLoader.timeout = 20;
|
|
[objectManager loadObjectsAtResourcePath:@"/empty/array" delegate:responseLoader];
|
|
[responseLoader waitForResponse];
|
|
assertThat(responseLoader.objects, isNot(nilValue()));
|
|
assertThatBool([responseLoader.objects isKindOfClass:[NSArray class]], is(equalToBool(YES)));
|
|
assertThat(responseLoader.objects, is(empty()));
|
|
}
|
|
|
|
- (void)testShouldInvokeTheDelegateOnSuccessIfTheResponseIsAnEmptyDictionary
|
|
{
|
|
RKObjectManager *objectManager = [RKTestFactory objectManager];
|
|
RKTestResponseLoader *responseLoader = [RKTestResponseLoader responseLoader];
|
|
responseLoader.timeout = 20;
|
|
[objectManager loadObjectsAtResourcePath:@"/empty/dictionary" delegate:responseLoader];
|
|
[responseLoader waitForResponse];
|
|
assertThat(responseLoader.objects, isNot(nilValue()));
|
|
assertThatBool([responseLoader.objects isKindOfClass:[NSArray class]], is(equalToBool(YES)));
|
|
assertThat(responseLoader.objects, is(empty()));
|
|
}
|
|
|
|
- (void)testShouldInvokeTheDelegateOnSuccessIfTheResponseIsAnEmptyString
|
|
{
|
|
RKObjectManager *objectManager = [RKTestFactory objectManager];
|
|
RKTestResponseLoader *responseLoader = [RKTestResponseLoader responseLoader];
|
|
responseLoader.timeout = 20;
|
|
[objectManager loadObjectsAtResourcePath:@"/empty/string" delegate:responseLoader];
|
|
[responseLoader waitForResponse];
|
|
assertThat(responseLoader.objects, isNot(nilValue()));
|
|
assertThatBool([responseLoader.objects isKindOfClass:[NSArray class]], is(equalToBool(YES)));
|
|
assertThat(responseLoader.objects, is(empty()));
|
|
}
|
|
|
|
- (void)testShouldNotBlockNetworkOperationsWhileAwaitingObjectMapping
|
|
{
|
|
RKObjectManager *objectManager = [RKTestFactory objectManager];
|
|
objectManager.requestCache.storagePolicy = RKRequestCacheStoragePolicyDisabled;
|
|
objectManager.client.requestQueue.concurrentRequestsLimit = 1;
|
|
RKObjectMapping *userMapping = [RKObjectMapping mappingForClass:[RKTestComplexUser class]];
|
|
userMapping.rootKeyPath = @"human";
|
|
[userMapping mapAttributes:@"name", @"id", nil];
|
|
|
|
// Suspend the Queue to block object mapping
|
|
[objectManager.mappingQueue setSuspended:YES];
|
|
|
|
RKTestResponseLoader *responseLoader = [RKTestResponseLoader responseLoader];
|
|
[objectManager.mappingProvider setObjectMapping:userMapping forResourcePathPattern:@"/humans/1"];
|
|
[objectManager loadObjectsAtResourcePath:@"/humans/1" delegate:nil];
|
|
[objectManager.client get:@"/empty/string" delegate:responseLoader];
|
|
[responseLoader waitForResponse];
|
|
|
|
// We should get a response is network is released even though object mapping didn't finish
|
|
assertThatBool(responseLoader.wasSuccessful, is(equalToBool(YES)));
|
|
}
|
|
|
|
#pragma mark - Block Tests
|
|
|
|
- (void)testInvocationOfDidLoadObjectBlock
|
|
{
|
|
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[RKTestFactory baseURL]];
|
|
RKTestResponseLoader *responseLoader = [RKTestResponseLoader responseLoader];
|
|
RKObjectLoader *objectLoader = [objectManager loaderWithResourcePath:@"/JSON/ComplexNestedUser.json"];
|
|
objectLoader.delegate = responseLoader;
|
|
objectLoader.method = RKRequestMethodGET;
|
|
objectLoader.mappingProvider = [self providerForComplexUser];
|
|
__block id expectedResult = nil;
|
|
objectLoader.onDidLoadObject = ^(id object) {
|
|
expectedResult = object;
|
|
};
|
|
|
|
[objectLoader sendAsynchronously];
|
|
[responseLoader waitForResponse];
|
|
assertThat(expectedResult, is(notNilValue()));
|
|
}
|
|
|
|
- (void)testInvocationOfDidLoadObjectBlockIsSingularObjectOfCorrectType
|
|
{
|
|
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[RKTestFactory baseURL]];
|
|
RKTestResponseLoader *responseLoader = [RKTestResponseLoader responseLoader];
|
|
RKObjectLoader *objectLoader = [objectManager loaderWithResourcePath:@"/JSON/ComplexNestedUser.json"];
|
|
objectLoader.delegate = responseLoader;
|
|
objectLoader.method = RKRequestMethodGET;
|
|
objectLoader.mappingProvider = [self providerForComplexUser];
|
|
__block id expectedResult = nil;
|
|
objectLoader.onDidLoadObject = ^(id object) {
|
|
expectedResult = object;
|
|
};
|
|
|
|
[objectLoader sendAsynchronously];
|
|
[responseLoader waitForResponse];
|
|
assertThat(expectedResult, is(instanceOf([RKTestComplexUser class])));
|
|
}
|
|
|
|
- (void)testInvocationOfDidLoadObjectsBlock
|
|
{
|
|
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[RKTestFactory baseURL]];
|
|
RKTestResponseLoader *responseLoader = [RKTestResponseLoader responseLoader];
|
|
RKObjectLoader *objectLoader = [objectManager loaderWithResourcePath:@"/JSON/ComplexNestedUser.json"];
|
|
objectLoader.delegate = responseLoader;
|
|
objectLoader.method = RKRequestMethodGET;
|
|
objectLoader.mappingProvider = [self providerForComplexUser];
|
|
__block id expectedResult = nil;
|
|
objectLoader.onDidLoadObjects = ^(NSArray *objects) {
|
|
expectedResult = objects;
|
|
};
|
|
|
|
[objectLoader sendAsynchronously];
|
|
[responseLoader waitForResponse];
|
|
assertThat(expectedResult, is(notNilValue()));
|
|
}
|
|
|
|
- (void)testInvocationOfDidLoadObjectsBlocksIsCollectionOfObjects
|
|
{
|
|
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[RKTestFactory baseURL]];
|
|
RKTestResponseLoader *responseLoader = [RKTestResponseLoader responseLoader];
|
|
RKObjectLoader *objectLoader = [objectManager loaderWithResourcePath:@"/JSON/ComplexNestedUser.json"];
|
|
objectLoader.delegate = responseLoader;
|
|
objectLoader.method = RKRequestMethodGET;
|
|
objectLoader.mappingProvider = [self providerForComplexUser];
|
|
__block id expectedResult = nil;
|
|
objectLoader.onDidLoadObjects = ^(NSArray *objects) {
|
|
expectedResult = [objects retain];
|
|
};
|
|
|
|
[objectLoader sendAsynchronously];
|
|
[responseLoader waitForResponse];
|
|
NSLog(@"The expectedResult = %@", expectedResult);
|
|
assertThat(expectedResult, is(instanceOf([NSArray class])));
|
|
assertThat(expectedResult, hasCountOf(1));
|
|
[expectedResult release];
|
|
}
|
|
|
|
- (void)testInvocationOfDidLoadObjectsDictionaryBlock
|
|
{
|
|
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[RKTestFactory baseURL]];
|
|
RKTestResponseLoader *responseLoader = [RKTestResponseLoader responseLoader];
|
|
RKObjectLoader *objectLoader = [objectManager loaderWithResourcePath:@"/JSON/ComplexNestedUser.json"];
|
|
objectLoader.delegate = responseLoader;
|
|
objectLoader.method = RKRequestMethodGET;
|
|
objectLoader.mappingProvider = [self providerForComplexUser];
|
|
__block id expectedResult = nil;
|
|
objectLoader.onDidLoadObjectsDictionary = ^(NSDictionary *dictionary) {
|
|
expectedResult = dictionary;
|
|
};
|
|
|
|
[objectLoader sendAsynchronously];
|
|
[responseLoader waitForResponse];
|
|
assertThat(expectedResult, is(notNilValue()));
|
|
}
|
|
|
|
- (void)testInvocationOfDidLoadObjectsDictionaryBlocksIsDictionaryOfObjects
|
|
{
|
|
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[RKTestFactory baseURL]];
|
|
RKTestResponseLoader *responseLoader = [RKTestResponseLoader responseLoader];
|
|
RKObjectLoader *objectLoader = [objectManager loaderWithResourcePath:@"/JSON/ComplexNestedUser.json"];
|
|
objectLoader.delegate = responseLoader;
|
|
objectLoader.method = RKRequestMethodGET;
|
|
objectLoader.mappingProvider = [self providerForComplexUser];
|
|
__block id expectedResult = nil;
|
|
objectLoader.onDidLoadObjectsDictionary = ^(NSDictionary *dictionary) {
|
|
expectedResult = dictionary;
|
|
};
|
|
|
|
[objectLoader sendAsynchronously];
|
|
[responseLoader waitForResponse];
|
|
assertThat(expectedResult, is(instanceOf([NSDictionary class])));
|
|
assertThat(expectedResult, hasCountOf(1));
|
|
}
|
|
|
|
// NOTE: Errors are fired in a number of contexts within the RKObjectLoader. We have centralized the cases into a private
|
|
// method and test that one case here. There should be better coverage for this.
|
|
- (void)testInvocationOfOnDidFailWithError
|
|
{
|
|
RKObjectLoader *loader = [RKObjectLoader loaderWithURL:nil mappingProvider:nil];
|
|
NSError *expectedError = [NSError errorWithDomain:@"Testing" code:1234 userInfo:nil];
|
|
__block NSError *blockError = nil;
|
|
loader.onDidFailWithError = ^(NSError *error) {
|
|
blockError = error;
|
|
};
|
|
[loader performSelector:@selector(informDelegateOfError:) withObject:expectedError];
|
|
assertThat(blockError, is(equalTo(expectedError)));
|
|
}
|
|
|
|
- (void)testShouldNotAssertDuringObjectMappingOnSynchronousRequest
|
|
{
|
|
RKObjectManager *objectManager = [RKTestFactory objectManager];
|
|
|
|
RKObjectMapping *userMapping = [RKObjectMapping mappingForClass:[RKTestComplexUser class]];
|
|
userMapping.rootKeyPath = @"data.STUser";
|
|
[userMapping mapAttributes:@"firstname", nil];
|
|
RKObjectLoader *objectLoader = [objectManager loaderWithResourcePath:@"/humans/1"];
|
|
objectLoader.objectMapping = userMapping;
|
|
[objectLoader sendSynchronously];
|
|
RKResponse *response = [objectLoader sendSynchronously];
|
|
|
|
assertThatInteger(response.statusCode, is(equalToInt(200)));
|
|
}
|
|
|
|
@end
|