mirror of
https://github.com/zhigang1992/RestKit.git
synced 2026-04-03 09:45:10 +08:00
classes to eliminate issues with duplicated objects. closes #611, #612, #613, #618 * NSEntityDescription is now aware of the primaryKeyAttribute. Can be configured via Interface Builder within Xcode or programatically. * Added findByPrimaryKey: interface to the Core Data extensions. * Relaxed dependencies on RKManagedObjectMapping across the system now that primaryKey is available without a reference to the mapping.
297 lines
15 KiB
Objective-C
297 lines
15 KiB
Objective-C
//
|
|
// RKInMemoryEntityCacheTest.m
|
|
// RestKit
|
|
//
|
|
// Created by Jeff Arena on 1/25/12.
|
|
// Copyright (c) 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 "RKHuman.h"
|
|
|
|
@interface RKInMemoryEntityCache ()
|
|
@property(nonatomic, retain) NSMutableDictionary *entityCache;
|
|
|
|
- (BOOL)shouldCoerceAttributeToString:(NSString *)attribute forEntity:(NSEntityDescription *)entity;
|
|
- (NSManagedObject *)objectWithID:(NSManagedObjectID *)objectID inContext:(NSManagedObjectContext *)managedObjectContext;
|
|
@end
|
|
|
|
@interface RKInMemoryEntityCacheTest : RKTestCase
|
|
|
|
@end
|
|
|
|
@implementation RKInMemoryEntityCacheTest
|
|
|
|
- (void)testInitializationWithManagedObjectContext
|
|
{
|
|
RKManagedObjectStore *objectStore = [RKTestFactory managedObjectStore];
|
|
RKInMemoryEntityCache *cache = [[RKInMemoryEntityCache alloc] initWithManagedObjectContext:objectStore.primaryManagedObjectContext];
|
|
assertThat(cache.managedObjectContext, is(equalTo(objectStore.primaryManagedObjectContext)));
|
|
}
|
|
|
|
- (void)testShouldCoercePrimaryKeysToStringsForLookup {
|
|
RKManagedObjectStore* objectStore = [RKTestFactory managedObjectStore];
|
|
RKHuman* human = [RKHuman createEntity];
|
|
human.railsID = [NSNumber numberWithInt:1234];
|
|
[objectStore save:nil];
|
|
|
|
RKInMemoryEntityCache *entityCache = [[[RKInMemoryEntityCache alloc] init] autorelease];
|
|
assertThatBool([entityCache shouldCoerceAttributeToString:@"railsID" forEntity:human.entity], is(equalToBool(YES)));
|
|
}
|
|
|
|
- (void)testShouldCacheAllObjectsForEntityWhenAccessingEntityCache {
|
|
RKManagedObjectStore* objectStore = [RKTestFactory managedObjectStore];
|
|
RKHuman* human = [RKHuman createEntity];
|
|
human.railsID = [NSNumber numberWithInt:1234];
|
|
[objectStore save:nil];
|
|
|
|
RKInMemoryEntityCache *entityCache = [[[RKInMemoryEntityCache alloc] init] autorelease];
|
|
NSMutableDictionary *humanCache = [entityCache cachedObjectsForEntity:human.entity
|
|
byAttribute:@"railsID"
|
|
inContext:objectStore.primaryManagedObjectContext];
|
|
assertThatInteger([humanCache count], is(equalToInt(1)));
|
|
}
|
|
|
|
- (void)testShouldCacheAllObjectsForEntityWhenAsked {
|
|
RKManagedObjectStore* objectStore = [RKTestFactory managedObjectStore];
|
|
RKHuman* human = [RKHuman createEntity];
|
|
human.railsID = [NSNumber numberWithInt:1234];
|
|
[objectStore save:nil];
|
|
|
|
RKInMemoryEntityCache *entityCache = [[[RKInMemoryEntityCache alloc] init] autorelease];
|
|
[entityCache cacheObjectsForEntity:human.entity byAttribute:@"railsID" inContext:objectStore.primaryManagedObjectContext];
|
|
NSMutableDictionary *humanCache = [entityCache cachedObjectsForEntity:human.entity
|
|
byAttribute:@"railsID"
|
|
inContext:objectStore.primaryManagedObjectContext];
|
|
assertThatInteger([humanCache count], is(equalToInt(1)));
|
|
}
|
|
|
|
- (void)testShouldRetrieveObjectsProperlyFromTheEntityCache {
|
|
RKManagedObjectStore* objectStore = [RKTestFactory managedObjectStore];
|
|
RKHuman* human = [RKHuman createEntity];
|
|
human.railsID = [NSNumber numberWithInt:1234];
|
|
[objectStore save:nil];
|
|
|
|
RKInMemoryEntityCache *entityCache = [[[RKInMemoryEntityCache alloc] init] autorelease];
|
|
NSManagedObject *cachedInstance = [entityCache cachedObjectForEntity:human.entity
|
|
withAttribute:@"railsID"
|
|
value:[NSNumber numberWithInt:1234]
|
|
inContext:objectStore.primaryManagedObjectContext];
|
|
assertThat(cachedInstance, is(equalTo(human)));
|
|
}
|
|
|
|
- (void)testShouldCacheAnIndividualObjectWhenAsked {
|
|
RKManagedObjectStore* objectStore = [RKTestFactory managedObjectStore];
|
|
RKHuman* human = [RKHuman createEntity];
|
|
human.railsID = [NSNumber numberWithInt:1234];
|
|
[objectStore save:nil];
|
|
|
|
RKInMemoryEntityCache *entityCache = [[[RKInMemoryEntityCache alloc] init] autorelease];
|
|
NSMutableDictionary *humanCache = [entityCache cachedObjectsForEntity:human.entity
|
|
byAttribute:@"railsID"
|
|
inContext:objectStore.primaryManagedObjectContext];
|
|
assertThatInteger([humanCache count], is(equalToInt(1)));
|
|
|
|
RKHuman* newHuman = [RKHuman createEntity];
|
|
newHuman.railsID = [NSNumber numberWithInt:5678];
|
|
|
|
[entityCache cacheObject:newHuman byAttribute:@"railsID" inContext:objectStore.primaryManagedObjectContext];
|
|
[entityCache cacheObjectsForEntity:human.entity byAttribute:@"railsID" inContext:objectStore.primaryManagedObjectContext];
|
|
humanCache = [entityCache cachedObjectsForEntity:human.entity
|
|
byAttribute:@"railsID"
|
|
inContext:objectStore.primaryManagedObjectContext];
|
|
assertThatInteger([humanCache count], is(equalToInt(2)));
|
|
}
|
|
|
|
- (void)testShouldCacheAnIndividualObjectByPrimaryKeyValueWhenAsked {
|
|
RKManagedObjectStore* objectStore = [RKTestFactory managedObjectStore];
|
|
RKHuman* human = [RKHuman createEntity];
|
|
human.railsID = [NSNumber numberWithInt:1234];
|
|
[objectStore save:nil];
|
|
|
|
RKInMemoryEntityCache *entityCache = [[[RKInMemoryEntityCache alloc] init] autorelease];
|
|
NSMutableDictionary *humanCache = [entityCache cachedObjectsForEntity:human.entity
|
|
byAttribute:@"railsID"
|
|
inContext:objectStore.primaryManagedObjectContext];
|
|
assertThatInteger([humanCache count], is(equalToInt(1)));
|
|
|
|
RKHuman* newHuman = [RKHuman createEntity];
|
|
newHuman.railsID = [NSNumber numberWithInt:5678];
|
|
[objectStore save:nil];
|
|
|
|
[entityCache cacheObject:newHuman.entity
|
|
byAttribute:@"railsID"
|
|
value:[NSNumber numberWithInt:5678]
|
|
inContext:objectStore.primaryManagedObjectContext];
|
|
[entityCache cacheObjectsForEntity:human.entity byAttribute:@"railsID" inContext:objectStore.primaryManagedObjectContext];
|
|
|
|
humanCache = [entityCache cachedObjectsForEntity:human.entity byAttribute:@"railsID" inContext:objectStore.primaryManagedObjectContext];
|
|
assertThatInteger([humanCache count], is(equalToInt(2)));
|
|
}
|
|
|
|
- (void)testShouldExpireACacheEntryForAnObjectWhenAsked {
|
|
RKManagedObjectStore* objectStore = [RKTestFactory managedObjectStore];
|
|
RKHuman* human = [RKHuman createEntity];
|
|
human.railsID = [NSNumber numberWithInt:1234];
|
|
[objectStore save:nil];
|
|
|
|
RKInMemoryEntityCache *entityCache = [[[RKInMemoryEntityCache alloc] init] autorelease];
|
|
NSMutableDictionary *humanCache = [entityCache cachedObjectsForEntity:human.entity
|
|
byAttribute:@"railsID"
|
|
inContext:objectStore.primaryManagedObjectContext];
|
|
assertThatInteger([humanCache count], is(equalToInt(1)));
|
|
|
|
[entityCache expireCacheEntryForObject:human byAttribute:@"railsID" inContext:objectStore.primaryManagedObjectContext];
|
|
assertThatInteger([entityCache.entityCache count], is(equalToInt(0)));
|
|
}
|
|
|
|
- (void)testShouldExpireEntityCacheWhenAsked {
|
|
RKManagedObjectStore* objectStore = [RKTestFactory managedObjectStore];
|
|
RKHuman* human = [RKHuman createEntity];
|
|
human.railsID = [NSNumber numberWithInt:1234];
|
|
[objectStore save:nil];
|
|
|
|
RKInMemoryEntityCache *entityCache = [[[RKInMemoryEntityCache alloc] init] autorelease];
|
|
NSMutableDictionary *humanCache = [entityCache cachedObjectsForEntity:human.entity
|
|
byAttribute:@"railsID"
|
|
inContext:objectStore.primaryManagedObjectContext];
|
|
assertThatInteger([humanCache count], is(equalToInt(1)));
|
|
|
|
[entityCache expireCacheEntriesForEntity:human.entity];
|
|
assertThatInteger([entityCache.entityCache count], is(equalToInt(0)));
|
|
}
|
|
|
|
#if TARGET_OS_IPHONE
|
|
- (void)testShouldExpireEntityCacheInResponseToMemoryWarning {
|
|
RKManagedObjectStore* objectStore = [RKTestFactory managedObjectStore];
|
|
RKHuman* human = [RKHuman createEntity];
|
|
human.railsID = [NSNumber numberWithInt:1234];
|
|
[objectStore save:nil];
|
|
|
|
RKInMemoryEntityCache *entityCache = [[[RKInMemoryEntityCache alloc] init] autorelease];
|
|
NSMutableDictionary *humanCache = [entityCache cachedObjectsForEntity:human.entity
|
|
byAttribute:@"railsID"
|
|
inContext:objectStore.primaryManagedObjectContext];
|
|
assertThatInteger([humanCache count], is(equalToInt(1)));
|
|
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationDidReceiveMemoryWarningNotification object:nil];
|
|
assertThatInteger([entityCache.entityCache count], is(equalToInt(0)));
|
|
}
|
|
#endif
|
|
|
|
- (void)testShouldAddInstancesOfInsertedObjectsToCache {
|
|
RKManagedObjectStore* objectStore = [RKTestFactory managedObjectStore];
|
|
RKHuman* human = [RKHuman createEntity];
|
|
human.railsID = [NSNumber numberWithInt:1234];
|
|
[objectStore save:nil];
|
|
|
|
RKInMemoryEntityCache *entityCache = [[[RKInMemoryEntityCache alloc] init] autorelease];
|
|
NSMutableDictionary *humanCache = [entityCache cachedObjectsForEntity:human.entity
|
|
byAttribute:@"railsID"
|
|
inContext:objectStore.primaryManagedObjectContext];
|
|
assertThatInteger([humanCache count], is(equalToInt(1)));
|
|
|
|
RKHuman* newHuman = [RKHuman createEntity];
|
|
newHuman.railsID = [NSNumber numberWithInt:5678];
|
|
[objectStore save:nil];
|
|
|
|
humanCache = [entityCache cachedObjectsForEntity:human.entity
|
|
byAttribute:@"railsID"
|
|
inContext:objectStore.primaryManagedObjectContext];
|
|
assertThatInteger([humanCache count], is(equalToInt(2)));
|
|
}
|
|
|
|
- (void)testShouldRemoveInstancesOfDeletedObjectsToCache {
|
|
RKManagedObjectStore* objectStore = [RKTestFactory managedObjectStore];
|
|
RKHuman* humanOne = [RKHuman createEntity];
|
|
humanOne.railsID = [NSNumber numberWithInt:1234];
|
|
|
|
RKHuman* humanTwo = [RKHuman createEntity];
|
|
humanTwo.railsID = [NSNumber numberWithInt:5678];
|
|
[objectStore save:nil];
|
|
|
|
RKInMemoryEntityCache *entityCache = [[[RKInMemoryEntityCache alloc] init] autorelease];
|
|
NSMutableDictionary *humanCache = [entityCache cachedObjectsForEntity:humanOne.entity
|
|
byAttribute:@"railsID"
|
|
inContext:objectStore.primaryManagedObjectContext];
|
|
assertThatInteger([humanCache count], is(equalToInt(2)));
|
|
|
|
[humanTwo deleteEntity];
|
|
[objectStore save:nil];
|
|
|
|
humanCache = [entityCache cachedObjectsForEntity:humanOne.entity
|
|
byAttribute:@"railsID"
|
|
inContext:objectStore.primaryManagedObjectContext];
|
|
assertThatInteger([humanCache count], is(equalToInt(1)));
|
|
}
|
|
|
|
- (void)testThatDeletionOfObjectsDoesNotPermitCreationOfDuplicates {
|
|
RKManagedObjectStore* objectStore = [RKTestFactory managedObjectStore];
|
|
RKHuman* humanOne = [RKHuman createEntity];
|
|
humanOne.railsID = [NSNumber numberWithInt:1234];
|
|
|
|
RKHuman* humanTwo = [RKHuman createEntity];
|
|
humanTwo.railsID = [NSNumber numberWithInt:5678];
|
|
[objectStore save:nil];
|
|
|
|
RKInMemoryEntityCache *entityCache = [[[RKInMemoryEntityCache alloc] init] autorelease];
|
|
NSMutableDictionary *humanCache = [entityCache cachedObjectsForEntity:humanOne.entity
|
|
byAttribute:@"railsID"
|
|
inContext:objectStore.primaryManagedObjectContext];
|
|
assertThatInteger([humanCache count], is(equalToInt(2)));
|
|
|
|
[humanTwo deleteEntity];
|
|
[objectStore save:nil];
|
|
|
|
RKHuman *existingReference = (RKHuman *)[entityCache cachedObjectForEntity:[RKHuman entity] withAttribute:@"railsID" value:[NSNumber numberWithInt:1234] inContext:objectStore.primaryManagedObjectContext];
|
|
|
|
assertThat(existingReference, is(notNilValue()));
|
|
assertThat(existingReference, is(equalTo(humanOne)));
|
|
}
|
|
|
|
- (void)testThatRepeatedInvocationsOfLoadObjectDoesNotDuplicateObjects {
|
|
RKManagedObjectStore *objectStore = [RKTestFactory managedObjectStore];
|
|
objectStore.cacheStrategy = [RKInMemoryManagedObjectCache new];
|
|
RKObjectManager *objectManager = [RKTestFactory objectManager];
|
|
objectManager.objectStore = objectStore;
|
|
RKManagedObjectMapping *humanMapping = [RKManagedObjectMapping mappingForClass:[RKHuman class] inManagedObjectStore:objectStore];
|
|
humanMapping.primaryKeyAttribute = @"name";
|
|
[humanMapping mapKeyPath:@"id" toAttribute:@"railsID"];
|
|
[humanMapping mapAttributes:@"name", nil];
|
|
[objectManager.mappingProvider setObjectMapping:humanMapping forKeyPath:@"human"];
|
|
|
|
for (NSUInteger i = 0; i < 5; i++) {
|
|
RKTestResponseLoader *responseLoader = [RKTestResponseLoader responseLoader];
|
|
[objectManager loadObjectsAtResourcePath:@"/JSON/ArrayOfHumans.json" delegate:responseLoader];
|
|
[responseLoader waitForResponse];
|
|
for (RKHuman *object in [RKHuman allObjects]) {
|
|
if ([object.railsID intValue] == 201) {
|
|
[objectStore.managedObjectContextForCurrentThread deleteObject:object];
|
|
[objectStore.managedObjectContextForCurrentThread save:nil];
|
|
}
|
|
}
|
|
|
|
[objectStore save:nil];
|
|
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.2]];
|
|
}
|
|
|
|
NSUInteger count = [RKHuman count:nil];
|
|
assertThatInt(count, is(equalToInt(1)));
|
|
NSArray *humans = [RKHuman allObjects];
|
|
[humans makeObjectsPerformSelector:@selector(railsID)];
|
|
}
|
|
|
|
@end
|