2014-02-01 3 views
1

Я использую RestKit ~> 0.20.3 и RestKit/Testing ~> 0.20.3. Так что это пример моего отображения:RestKit RKMappingTest JSON array

RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[PlayerVO class]]; 
[mapping addAttributeMappingsFromArray:@[@"firstName", @"middeName", @"lastName", @"dob", @"sex"]]; 

Это мой фиктивный данные:

NSDictionary *data = @{@"players": @[@{@"firstName": @"Ahmed", @"middleName": @"Ahmed", @"lastName": @"Ahmed", @"dob": @"100", @"sex": @"m"}]}; 

Это мой mappingTest:

RKMappingTest *mappingTest = [RKMappingTest testForMapping:mapping sourceObject:data destinationObject:nil]; 

И, наконец, мой expectation:

RKPropertyMappingTestExpectation *expectation = [RKPropertyMappingTestExpectation expectationWithSourceKeyPath:@"players.firstName" destinationKeyPath:@"firstName" evaluationBlock:^BOOL(RKPropertyMappingTestExpectation *expectation, RKPropertyMapping *mapping, id mappedValue, NSError *__autoreleasing *error) { 
    BOOL expect = [mappedValue length] > 0; 

    XCTAssertTrue(expect); 

    return expect; 
}]; 

[mappingTest addExpectation:expectation]; 

XCTAssertTrue([mappingTest evaluate]); 
XCTAssertNoThrow([mappingTest verify]); 

Таким образом, этот тест завершился неудачно, поскольку, похоже, я не могу указать путь к следующему ключу, поскольку data является массивом. Это ошибка, я получаю:

testPlayerServiceGetPlayers] : (([mappingTest verify]) does not throw) failed: throwing "0x8e7d770: failed with error: (null) 
RKMappingTest Expectations: (
    "map 'players.firstName' to 'firstName' satisfying evaluation block" 
) 
Events: (
) during mapping from { 
    players =  (
       { 
      dob = 100; 
      firstName = Ahmed; 
      lastName = Ahmed; 
      middleName = Ahmed; 
      sex = m; 
     } 
    ); 
} to (null) with mapping <RKObjectMapping:0x8e6aad0 objectClass=PlayerVO propertyMappings=(
    "<RKAttributeMapping: 0x8e6b880 firstName => firstName>", 
    "<RKAttributeMapping: 0x8e61df0 middeName => middeName>", 
    "<RKAttributeMapping: 0x8e2f580 lastName => lastName>", 
    "<RKAttributeMapping: 0x8e67a60 dob => dob>", 
    "<RKAttributeMapping: 0x8e2c120 sex => sex>" 
)>" 

Если изменить свои данные, чтобы:

NSDictionary *data = @{@"firstName": @"Ahmed", @"middleName": @"Naseer", @"lastName": @"Nuaman", @"dob": @"524534400", @"sex": @"m"}; 

И expectation «s expectationWithSourceKeyPath к @"firstName", тесты проходят. Поэтому это заставляет меня думать, что проблема явно связана с установкой ключевого пути. Теперь в моем приложении, что это сделано с помощью:

RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping method:RKRequestMethodAny pathPattern:nil keyPath:@"players" statusCodes:statusCodes]; 

Однако я не могу найти способ настройки keyPath для RKMappingTest или RKPropertyMappingTestExpectation, какие-либо идеи о том, как я могу добиться этого?

Update

Так что я имел взгляд через RKMappingTest.h и нашел rootKeyPath. Я установил следующее:

mappingTest.rootKeyPath = @"players"; 

И еще были проблемы, касающиеся mappedValue в RKPropertyMappingTestExpectation. Так что я также изменил мои данные на этом:

NSDictionary *data = @{@"players": @{@"firstName": @"Ahmed", @"middleName": @"Ahmed", @"lastName": @"Ahmed", @"dob": @"100", @"sex": @"m"}}; 

И теперь я могу видеть, что mappedValue теперь установлено в Ahmed и обновил RKPropertyMappingTestExpectation к следующему:

RKPropertyMappingTestExpectation *expectation = [RKPropertyMappingTestExpectation expectationWithSourceKeyPath:@"firstName" destinationKeyPath:@"firstName" evaluationBlock:^BOOL(RKPropertyMappingTestExpectation *expectation, RKPropertyMapping *mapping, id mappedValue, NSError *__autoreleasing *error) { 
    return [mappedValue isEqualToString:@"Ahmed"]; 
}]; 

Но это с помощью объекта, а чем массив. Есть еще предложения?

ответ

0

Вы думаете о тестировании, а точнее, об объеме тестирования, ошибочно. Это единичный тест, а единица - это отображение. Отображение относится к отдельным элементам, и поэтому ваш модифицированный тест работает, потому что область действия верна.

Дескрипторы ответа имеют разный объем. Вы не можете проверить объем дескриптора ответа в тесте сопоставления.

+1

Хм, это не кажется правильным. Почему я не могу тестировать сопоставление через посмеянный репрезентативный ответ с сервера? Поскольку RestKit должен быть набором инструментов для совершения вызовов на сервер, я хочу убедиться, что данные, которые я отправляю обратно, и способ, которым я сопоставляю и обрабатываю его, верны. –

+0

Но ваш ключевой путь не является частью отображения, поэтому он не является частью теста сопоставления. – Wain

+0

Итак, в чем смысл теста отображения? –

1

Я думаю, что я нашел несколько лучший ответ, чем ответ «вы испытываете неправильно». Вы должны быть в состоянии проверить надлежащим образом, обернув ваше сопоставление под тестом в другом сопоставлении.

// Data (in your case, you've used a hard coded string here) 
id fixtureData = [RKTestFixture parsedObjectWithContentsOfFixture:@"fixture.json"]; 

// Setup 
RKObjectMapping* wrapperMapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]]; 
RKObjectMapping *mappingToTest = [RKObjectMapping mappingForClass:[PlayerVO class]]; 
[mappingToTest addAttributeMappingsFromArray:@[@"firstName", @"middeName", @"lastName", @"dob", @"sex"]]; 
[wrapperMapping addRelationshipMappingWithSourceKeyPath:@"players" mapping:mappingToTest]; 
RKMappingTest* test = [RKMappingTest testForMapping:wrapperMapping sourceObject:fixtureData destinationObject:nil]; 

// If you're dealing with a managed object mapping, you'll need these: 
// I usually set up a single store in the "+(void)setUp" method and reset it 
// on each test in the "-(void)setUp" method. (note one method is class, one 
// is instance). 
//test.managedObjectContext = managedObjectStore.persistentStoreManagedObjectContext; 
//test.mappingOperationDataSource = [[RKManagedObjectMappingOperationDataSource alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext cache:[RKFetchRequestManagedObjectCache new]]; 

// Expectations 
[test addExpectation:[RKPropertyMappingTestExpectation expectationWithSourceKeyPath:@"..." destinationKeyPath:@"..."]]; 
// Add others as you see fit (these will work for the mappingToTest mapping). 

// Evaluate 
XCTAssert([test evaluate]); 
NSDictionary* result = test.destinationObject; 
// You can verify counts on the result and any other objects. 
// If you have variables in other structures you want tracked, you can expand 
// on the wrapper mapping. i.e. If your data contained a "teamName" at the 
// same level as your array of "players", you could add a mapping from 
// "teamName" to an arbitrary keyPath for your dictionary then access it in the 
// result variable. 

Это сработало для меня. Я думаю, что недальновидно говорить, что вы не должны тестировать коллекции. У вас может быть плохо спроектированный REST API, который требует этого, или сложное взаимодействие между управляемыми объектами, которые вы хотите проверить, правильно настроено, когда происходит сопоставление.

+0

Ваш код фактически не использует 'wrapperMapping' после его определения. Я предполагаю, что это опечатка на обеих линиях, начиная с '[mapping add ...', где первая должна использовать 'mappingToTest' и вторую' wrapperMapping'? – Wain

+0

@Wain Вы совершенно правы. Я транскрибировал из своего кода, который использовал имена переменных домена. Наверное, я плохо работал, переводя их. Я думаю, теперь это должно быть правильно. –

Смежные вопросы