Files
RestKit/Code/Testing/RKTestFactory.m

280 lines
9.3 KiB
Objective-C

//
// RKTestFactory.m
// RestKit
//
// Created by Blake Watters on 2/16/12.
// 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 "AFHTTPClient.h"
#import "RKTestFactory.h"
#import "RKLog.h"
#import "RKObjectManager.h"
#import "RKPathUtilities.h"
#import "RKMIMETypeSerialization.h"
#import "RKManagedObjectStore.h"
// Expose MIME Type singleton and initialization routine
@interface RKMIMETypeSerialization ()
+ (RKMIMETypeSerialization *)sharedSerialization;
- (void)addRegistrationsForKnownSerializations;
@end
@interface RKTestFactory ()
@property (nonatomic, strong) NSURL *baseURL;
@property (nonatomic, strong) NSMutableDictionary *factoryBlocks;
@property (nonatomic, strong) NSMutableDictionary *sharedObjectsByFactoryName;
@property (nonatomic, copy) void (^setUpBlock)();
@property (nonatomic, copy) void (^tearDownBlock)();
+ (RKTestFactory *)sharedFactory;
- (void)defineFactory:(NSString *)factoryName withBlock:(id (^)())block;
- (id)objectFromFactory:(NSString *)factoryName properties:(NSDictionary *)properties;
- (void)defineDefaultFactories;
@end
@implementation RKTestFactory
+ (void)initialize
{
// Ensure the shared factory is initialized
[self sharedFactory];
}
+ (RKTestFactory *)sharedFactory
{
static RKTestFactory *sharedFactory = nil;
if (! sharedFactory) {
sharedFactory = [RKTestFactory new];
}
return sharedFactory;
}
- (id)init
{
self = [super init];
if (self) {
self.baseURL = [NSURL URLWithString:@"http://127.0.0.1:4567"];
self.factoryBlocks = [NSMutableDictionary new];
self.sharedObjectsByFactoryName = [NSMutableDictionary new];
[self defineDefaultFactories];
}
return self;
}
- (void)defineFactory:(NSString *)factoryName withBlock:(id (^)())block
{
[self.factoryBlocks setObject:[block copy] forKey:factoryName];
}
- (id)objectFromFactory:(NSString *)factoryName properties:(NSDictionary *)properties
{
id (^block)() = [self.factoryBlocks objectForKey:factoryName];
NSAssert(block, @"No factory is defined with the name '%@'", factoryName);
id object = block();
[object setValuesForKeysWithDictionary:properties];
return object;
}
- (id)sharedObjectFromFactory:(NSString *)factoryName
{
id sharedObject = [self.sharedObjectsByFactoryName objectForKey:factoryName];
if (! sharedObject) {
sharedObject = [self objectFromFactory:factoryName properties:nil];
[self.sharedObjectsByFactoryName setObject:sharedObject forKey:factoryName];
}
return sharedObject;
}
- (void)defineDefaultFactories
{
[self defineFactory:RKTestFactoryDefaultNamesClient withBlock:^id {
__block AFHTTPClient *client;
RKLogSilenceComponentWhileExecutingBlock(RKlcl_cRestKitSupport, ^{
client = [AFHTTPClient clientWithBaseURL:self.baseURL];
});
return client;
}];
[self defineFactory:RKTestFactoryDefaultNamesObjectManager withBlock:^id {
__block RKObjectManager *objectManager;
RKLogSilenceComponentWhileExecutingBlock(RKlcl_cRestKitSupport, ^{
objectManager = [RKObjectManager managerWithBaseURL:self.baseURL];
});
return objectManager;
}];
[self defineFactory:RKTestFactoryDefaultNamesManagedObjectStore withBlock:^id {
NSString *storePath = [RKApplicationDataDirectory() stringByAppendingPathComponent:RKTestFactoryDefaultStoreFilename];
RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] init];
NSError *error;
NSPersistentStore *persistentStore = [managedObjectStore addSQLitePersistentStoreAtPath:storePath fromSeedDatabaseAtPath:nil withConfiguration:nil options:nil error:&error];
if (persistentStore) {
BOOL success = [managedObjectStore resetPersistentStores:&error];
if (! success) {
RKLogError(@"Failed to reset persistent store: %@", error);
}
}
return managedObjectStore;
}];
}
#pragma mark - Public Static Interface
+ (NSURL *)baseURL
{
return [RKTestFactory sharedFactory].baseURL;
}
+ (void)setBaseURL:(NSURL *)URL
{
[RKTestFactory sharedFactory].baseURL = URL;
}
+ (void)defineFactory:(NSString *)factoryName withBlock:(id (^)())block
{
[[RKTestFactory sharedFactory] defineFactory:factoryName withBlock:block];
}
+ (id)objectFromFactory:(NSString *)factoryName properties:(NSDictionary *)properties
{
return [[RKTestFactory sharedFactory] objectFromFactory:factoryName properties:properties];
}
+ (id)objectFromFactory:(NSString *)factoryName
{
return [[RKTestFactory sharedFactory] objectFromFactory:factoryName properties:nil];
}
+ (id)sharedObjectFromFactory:(NSString *)factoryName
{
return [[RKTestFactory sharedFactory] sharedObjectFromFactory:factoryName];
}
+ (id)insertManagedObjectForEntityForName:(NSString *)entityName
inManagedObjectContext:(NSManagedObjectContext *)managedObjectContext
withProperties:(NSDictionary *)properties
{
__block id managedObject;
__block NSError *error;
__block BOOL success;
if (! managedObjectContext) managedObjectContext = [[RKTestFactory managedObjectStore] mainQueueManagedObjectContext];
[managedObjectContext performBlockAndWait:^{
managedObject = [NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:managedObjectContext];
success = [managedObjectContext obtainPermanentIDsForObjects:@[managedObject] error:&error];
if (! success) {
RKLogWarning(@"Failed to obtain permanent objectID for managed object: %@", managedObject);
RKLogCoreDataError(error);
}
[managedObject setValuesForKeysWithDictionary:properties];
}];
return managedObject;
}
+ (NSSet *)factoryNames
{
return [NSSet setWithArray:[[RKTestFactory sharedFactory].factoryBlocks allKeys]];
}
+ (id)client
{
return [self sharedObjectFromFactory:RKTestFactoryDefaultNamesClient];
}
+ (id)objectManager
{
return [self sharedObjectFromFactory:RKTestFactoryDefaultNamesObjectManager];
}
+ (id)managedObjectStore
{
return [self sharedObjectFromFactory:RKTestFactoryDefaultNamesManagedObjectStore];
}
+ (void)setSetupBlock:(void (^)())block
{
[RKTestFactory sharedFactory].setUpBlock = block;
}
+ (void)setTearDownBlock:(void (^)())block
{
[RKTestFactory sharedFactory].tearDownBlock = block;
}
+ (void)setUp
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// On initial set up, perform a tear down to clear any state from the application launch
[self tearDown];
});
[[RKTestFactory sharedFactory].sharedObjectsByFactoryName removeAllObjects];
[RKObjectManager setSharedManager:nil];
[RKManagedObjectStore setDefaultStore:nil];
// Restore the default MIME Type Serializations in case a test has manipulated the registry
[[RKMIMETypeSerialization sharedSerialization] addRegistrationsForKnownSerializations];
// Delete the store if it exists
NSString *path = [RKApplicationDataDirectory() stringByAppendingPathComponent:RKTestFactoryDefaultStoreFilename];
if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
[[NSFileManager defaultManager] removeItemAtPath:path error:nil];
}
// Clear the NSURLCache
[[NSURLCache sharedURLCache] removeAllCachedResponses];
if ([RKTestFactory sharedFactory].setUpBlock) [RKTestFactory sharedFactory].setUpBlock();
}
+ (void)tearDown
{
if ([RKTestFactory sharedFactory].tearDownBlock) [RKTestFactory sharedFactory].tearDownBlock();
// Cancel any network operations and clear the cache
[[RKObjectManager sharedManager].operationQueue cancelAllOperations];
[[NSURLCache sharedURLCache] removeAllCachedResponses];
// Cancel any object mapping in the response mapping queue
[[RKObjectRequestOperation responseMappingQueue] cancelAllOperations];
// Ensure the existing defaultStore is shut down
[[NSNotificationCenter defaultCenter] removeObserver:[RKManagedObjectStore defaultStore]];
if ([[RKManagedObjectStore defaultStore] respondsToSelector:@selector(stopIndexingPersistentStoreManagedObjectContext)]) {
// Search component is optional
[[RKManagedObjectStore defaultStore] performSelector:@selector(stopIndexingPersistentStoreManagedObjectContext)];
if ([[RKManagedObjectStore defaultStore] respondsToSelector:@selector(searchIndexer)]) {
id searchIndexer = [[RKManagedObjectStore defaultStore] valueForKey:@"searchIndexer"];
[searchIndexer performSelector:@selector(cancelAllIndexingOperations)];
}
}
[[RKTestFactory sharedFactory].sharedObjectsByFactoryName removeAllObjects];
[RKObjectManager setSharedManager:nil];
[RKManagedObjectStore setDefaultStore:nil];
}
@end