我正在尝试测试我的Core Data模型的响应映射。我在Core Data模型中只有几个类,但其中有两个我测试很有趣。第一类是CTFUser
类,它保留有关用户的基本信息,第二类是CTFCharacter
类。用户可能只有很少的角色(某种类型的玩家)多对多关系。我想要做的是正确编写CTFUser
类的测试以及CTFUser
和CTFCharacter
类之间的关系。当我编写没有属性characters
的测试时,NSOrderedSet
类型测试已通过。当我尝试在不检查characters
value
次测试通过的RKPropertyMappingTestExpectation
的情况下测试属性{
"username": "tomkowz12",
"email": "tmk.szlc@gmail.com",
"password": "password123",
"nick": "black_lord",
"location": [10, 20],
"characters" : [{
"type": 1,
"total_time": 21,
"total_score": 100,
"health": 100,
"level": 20,
"is_active": 1
},
{
"type": 2,
"total_time": 23,
"total_score": 98,
"health": 55,
"level": 12,
"is_active": 0
}]
}
时。但是当我想检查这个映射的值时,我遇到了崩溃。
测试中使用的JSON夹具:
@interface CTFUser : CustomManagedObject
@property (nonatomic, retain) NSString * email;
@property (nonatomic, retain) NSString * nick;
@property (nonatomic, retain) NSString * username;
@property (nonatomic, retain) NSString * password;
@property (nonatomic, retain) id location;
@property (nonatomic, retain) CTFGame *game;
@property (nonatomic, retain) NSOrderedSet *characters;
+ (NSDictionary *)dictionaryForResponseMapping;
@end
CTFUser类
+ (NSDictionary *)dictionaryForResponseMapping {
return @{@"username" : @"username",
@"email" : @"email",
@"password" : @"password",
@"nick" : @"nick",
@"location" : @"location"};
}
和包含此类的属性映射的字典字典:
@interface CTFCharacter : CustomManagedObject
@property (nonatomic, retain) NSNumber * type;
@property (nonatomic, retain) NSNumber * totalTime;
@property (nonatomic, retain) NSNumber * totalScore;
@property (nonatomic, retain) NSNumber * health;
@property (nonatomic, retain) NSNumber * level;
@property (nonatomic, retain) NSNumber * active;
@property (nonatomic, retain) CTFUser *user;
+ (NSDictionary *)dictionaryResponseMapping;
@end
CTFCharacter class
+ (NSDictionary *)dictionaryResponseMapping {
return @{@"type": @"type",
@"total_time": @"totalTime",
@"total_score": @"totalScore",
@"health": @"health",
@"level": @"level",
@"is_active": @"active"};
}
带有属性映射的字典:
/// Configure mapping
RKEntityMapping *userMapping =
[RKEntityMapping mappingForEntityForName:NSStringFromClass([CTFUser class]) inManagedObjectStore:_manager.managedObjectStore];
[userMapping addAttributeMappingsFromDictionary:[CTFUser dictionaryForResponseMapping]];
RKEntityMapping *characterMapping =
[RKEntityMapping mappingForEntityForName:NSStringFromClass([CTFCharacter class]) inManagedObjectStore:_manager.managedObjectStore];
[characterMapping addAttributeMappingsFromDictionary:[CTFCharacter dictionaryResponseMapping]];
[userMapping addRelationshipMappingWithSourceKeyPath:@"characters" mapping:characterMapping];
/// Configure expectations
RKMappingTest *test = [RKMappingTest testForMapping:userMapping sourceObject:parsedJSON destinationObject:nil];
test.managedObjectContext = _service.managedObjectContext;
RKPropertyMappingTestExpectation *usernameExpectation =
[RKPropertyMappingTestExpectation expectationWithSourceKeyPath:@"username" destinationKeyPath:@"username" value:@"tomkowz12"];
[test addExpectation:usernameExpectation];
RKPropertyMappingTestExpectation *emailExpectation =
[RKPropertyMappingTestExpectation expectationWithSourceKeyPath:@"email" destinationKeyPath:@"email" value:@"tmk.szlc@gmail.com"];
[test addExpectation:emailExpectation];
RKPropertyMappingTestExpectation *passwordExpectation =
[RKPropertyMappingTestExpectation expectationWithSourceKeyPath:@"password" destinationKeyPath:@"password" value:@"password123"];
[test addExpectation:passwordExpectation];
RKPropertyMappingTestExpectation *nickExpectation =
[RKPropertyMappingTestExpectation expectationWithSourceKeyPath:@"nick" destinationKeyPath:@"nick" value:@"black_lord"];
[test addExpectation:nickExpectation];
RKPropertyMappingTestExpectation *locationExpectation =
[RKPropertyMappingTestExpectation expectationWithSourceKeyPath:@"location" destinationKeyPath:@"location" value:@[@(10), @(20)]];
[test addExpectation:locationExpectation];
/// Configure expectation objects
CTFCharacter *firstCharacter = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([CTFCharacter class]) inManagedObjectContext:_service.managedObjectContext];
firstCharacter.type = @(1);
firstCharacter.totalTime = @(21);
firstCharacter.totalScore = @(100);
firstCharacter.health = @(100);
firstCharacter.level = @(20);
firstCharacter.active = @YES;
CTFCharacter *secondCharacter = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([CTFCharacter class]) inManagedObjectContext:_service.managedObjectContext];
secondCharacter.type = @(2);
secondCharacter.totalTime = @(23);
secondCharacter.totalScore = @(98);
secondCharacter.health = @(55);
secondCharacter.level = @(12);
secondCharacter.active = @NO;
NSOrderedSet *set = [[NSOrderedSet alloc] initWithArray:@[firstCharacter, secondCharacter]];
RKPropertyMappingTestExpectation *charactersExpectation =
[RKPropertyMappingTestExpectation expectationWithSourceKeyPath:@"characters" destinationKeyPath:@"characters" value:set]; /// <-- this won't pass
// [RKPropertyMappingTestExpectation expectationWithSourceKeyPath:@"characters" destinationKeyPath:@"characters"]; /// <-- this pass
[test addExpectation:charactersExpectation];
[test verify];
}
**单元测试** - (void)testUserResponseMApping { id parsedJSON = [RKTestFixture parsedObjectWithContentsOfFixture:@“user-response.json”];
<unknown>:0: error: -[CTFUserTests testUserResponseMApping] : mapped to unexpected _NSFaultingMutableOrderedSet value 'Relationship 'characters' on managed object (0x8c4fba0) <CTFUser: 0x8c4fba0> (entity: CTFUser; id: 0x8c4d2a0 <x-coredata:///CTFUser/t28A63306-B2D2-41F5-A0C3-1BE85520B04710> ; data: {
characters = (
"0x8c52470 <x-coredata:///CTFCharacter/t28A63306-B2D2-41F5-A0C3-1BE85520B04711>",
"0x8c4d330 <x-coredata:///CTFCharacter/t28A63306-B2D2-41F5-A0C3-1BE85520B04712>"
);
email = "tmk.szlc@gmail.com";
game = nil;
location = "(\n 10,\n 20\n)";
nick = "black_lord";
password = password123;
username = tomkowz12;
}) with objects {(
<CTFCharacter: 0x8c528f0> (entity: CTFCharacter; id: 0x8c52470 <x-coredata:///CTFCharacter/t28A63306-B2D2-41F5-A0C3-1BE85520B04711> ; data: {
active = 1;
health = 100;
level = 20;
totalScore = 100;
totalTime = 21;
type = 1;
user = "0x8c4d2a0 <x-coredata:///CTFUser/t28A63306-B2D2-41F5-A0C3-1BE85520B04710>";
}),
<CTFCharacter: 0x8c4ef60> (entity: CTFCharacter; id: 0x8c4d330 <x-coredata:///CTFCharacter/t28A63306-B2D2-41F5-A0C3-1BE85520B04712> ; data: {
active = 0;
health = 55;
level = 12;
totalScore = 98;
totalTime = 23;
type = 2;
user = "0x8c4d2a0 <x-coredata:///CTFUser/t28A63306-B2D2-41F5-A0C3-1BE85520B04710>";
})
)}'
(
0 CoreFoundation 0x021185e4 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x01e9b8b6 objc_exception_throw + 44
2 CoreFoundation 0x021a86a1 -[NSException raise] + 17
3 Capture The FlagTests 0x0a0f1d60 -[RKMappingTest verifyExpectation:] + 464
4 Capture The FlagTests 0x0a0f2054 -[RKMappingTest verify] + 404
5 Capture The FlagTests 0x0a002cf0 -[CTFUserTests testUserResponseMApping] + 3648
6 CoreFoundation 0x0210cd1d __invoking___ + 29
7 CoreFoundation 0x0210cc2a -[NSInvocation invoke] + 362
8 XCTest 0x201032bf -[XCTestCase invokeTest] + 212
9 XCTest 0x2010338d -[XCTestCase performTest:] + 111
10 XCTest 0x2010417c -[XCTest run] + 82
11 XCTest 0x20102a44 -[XCTestSuite performTest:] + 139
12 XCTest 0x2010417c -[XCTest run] + 82
13 XCTest 0x20102a44 -[XCTestSuite performTest:] + 139
14 XCTest 0x2010417c -[XCTest run] + 82
15 XCTest 0x20102a44 -[XCTestSuite performTest:] + 139
16 XCTest 0x2010417c -[XCTest run] + 82
17 XCTest 0x20105aa1 +[XCTestProbe runTests:] + 183
18 Foundation 0x01ad212c __NSFireDelayedPerform + 372
19 CoreFoundation 0x020d6bd6 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 22
20 CoreFoundation 0x020d65bd __CFRunLoopDoTimer + 1181
21 CoreFoundation 0x020be628 __CFRunLoopRun + 1816
22 CoreFoundation 0x020bdac3 CFRunLoopRunSpecific + 467
23 CoreFoundation 0x020bd8db CFRunLoopRunInMode + 123
24 GraphicsServices 0x03ade9e2 GSEventRunModal + 192
25 GraphicsServices 0x03ade809 GSEventRun + 104
26 UIKit 0x00c09d3b UIApplicationMain + 1225
27 Capture The Flag 0x00008d0d main + 141
28 libdyld.dylib 0x0275670d start + 1
)
崩溃日志
characters
我犯了错误?应该如何测试- (void)getUser {
CoreDataService *_service = [CoreDataService sharedInstance];
RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:_service.managedObjectModel];
_connection.manager.managedObjectStore = managedObjectStore;
RKEntityMapping *userMapping =
[RKEntityMapping mappingForEntityForName:NSStringFromClass([CTFUser class]) inManagedObjectStore:managedObjectStore];
[userMapping addAttributeMappingsFromDictionary:[CTFUser dictionaryForResponseMapping]];
RKEntityMapping *characterMapping =
[RKEntityMapping mappingForEntityForName:NSStringFromClass([CTFCharacter class]) inManagedObjectStore:managedObjectStore];
[characterMapping addAttributeMappingsFromDictionary:[CTFCharacter dictionaryResponseMapping]];
[userMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"characters" toKeyPath:@"characters" withMapping:characterMapping]];
RKResponseDescriptor *descriptor = [RKResponseDescriptor responseDescriptorWithMapping:userMapping method:RKRequestMethodGET pathPattern:nil keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[_connection.manager addResponseDescriptor:descriptor];
[_connection.manager getObject:nil path:@"test" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
CTFUser *fetchedUser = (CTFUser *)mappingResult.firstObject;
NSLog(@"%@", fetchedUser);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(@"failure");
}];
}
属性的值?其他值正在测试中并通过。
编辑:
当我发出请求时,来自服务器的响应看起来很好,所有属性和关系都已正确映射,但仍然会出现测试问题。
{{1}}
提前谢谢。
答案 0 :(得分:0)
好的,我做到了。解决方法非常简单。昨天已经晚了所以我没有找到RestKit文档。
而不是使用:
expectationWithSourceKeyPath:destinationKeyPath:value:
我用过:
expectationWithSourceKeyPath:destinationKeyPath:evaluationBlock:
更改后的代码如下所示:
RKPropertyMappingTestExpectation *charactersExpectation =
[RKPropertyMappingTestExpectation expectationWithSourceKeyPath:@"characters" destinationKeyPath:@"characters" evaluationBlock:^BOOL(RKPropertyMappingTestExpectation *expectation, RKPropertyMapping *mapping, id mappedValue, NSError *__autoreleasing *error) {
NSArray *commitedKeysToCompare = @[@"type, totalTime, totalScore, healt, level, active"];
NSArray *array = [mappedValue allObjects];
BOOL containsTwoItems = array.count == 2;
/// Test First character
CTFCharacter *firstFetchedCharacter = (CTFCharacter *)array[0];
CTFCharacter *firstReferenceCharacter = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([CTFCharacter class]) inManagedObjectContext:_service.managedObjectContext];
firstReferenceCharacter.type = @(1);
firstReferenceCharacter.totalTime = @(21);
firstReferenceCharacter.totalScore = @(100);
firstReferenceCharacter.health = @(100);
firstReferenceCharacter.level = @(20);
firstReferenceCharacter.active = @YES;
BOOL isFirstEqual = [[firstFetchedCharacter committedValuesForKeys:commitedKeysToCompare] isEqual:[firstReferenceCharacter committedValuesForKeys:commitedKeysToCompare]];
/// Test Second character
CTFCharacter *secondFetchedCharacter = (CTFCharacter *)array[1];
CTFCharacter *secondReferenceCharacter = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([CTFCharacter class]) inManagedObjectContext:_service.managedObjectContext];
secondReferenceCharacter.type = @(2);
secondReferenceCharacter.totalTime = @(23);
secondReferenceCharacter.totalScore = @(98);
secondReferenceCharacter.health = @(55);
secondReferenceCharacter.level = @(12);
secondReferenceCharacter.active = @NO;
BOOL isSecondEqual = [[secondFetchedCharacter committedValuesForKeys:commitedKeysToCompare] isEqual:[secondReferenceCharacter committedValuesForKeys:commitedKeysToCompare]];
return isFirstEqual && isSecondEqual && containsTwoItems;
}];