Как провести юнит-тестирование NSCoding? - PullRequest
6 голосов
/ 25 ноября 2011

У меня есть приложение iOS с данными, сохраненными с использованием NSCoding и, точнее, NSKeyedArchiver. Это приложение уже доступно в App Store.

Я работаю над версией 2 приложения, и модель данных должна измениться. Поэтому мне нужно обработать миграцию модели данных. Я хочу, чтобы это охватывалось юнит-тестами.

В моих тестах я хочу динамически генерировать постоянные данные со старой моделью данных, запустить миграцию и посмотреть, все ли прошло хорошо.

В настоящее время архивация объекта выглядит следующим образом:

MyDataModelObject *object = ....
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeObject:object forKey:key];
[archiver finishEncoding];

Проблема в том, что MyDataModelObject может быть повторно проанализирован или даже удален во второй версии приложения. Поэтому я не могу использовать этот класс в своих тестах для создания «архива старой версии».

Есть ли способ имитировать то, что делается в методе encodeWithCoder: класса, без использования этого класса?


Я бы хотел добиться следующего

- testMigrationFrom_v1_to_v2 {
    // simulate an archive with v1 data model
    // I want this part of the code to be as simple as possible
    // I don't want to rely on old classes to generate the archive
    NSDictionary *person = ... // { firstName: John, lastName: Doe }
    NSDictionary *adress = ... // { street: 1 down street, city: Butterfly City }
    [person setObject:adress forKey:@"adress"];

    // there's something missing to tell the archiever that:
    // - person is of type OldPersonDataModel
    // - adress is of type OldAdressDataModel

    [archiver encodeObject:person forKey:@"somePerson"];
    // at this point, I would like the archive file to contain :
    // a person object of type OldPersonDataModel, that has an adress object of type OldAdressModel 

    NewPersonModel *newPerson =  [Migration readDataFromV1];

    // assertions
    NSAssert(newPerson.firstName, @"John");
    NSAssert(newPerson.lastName, @"Doe");
}

1 Ответ

1 голос
/ 28 ноября 2011

Я не совсем понимаю ваш вопрос, поэтому я дам вам два ответа:

Вы можете предварительно загрузить экземпляр NSDictionary ключами / значениями, которые вы использовали бы со своим старым классом, и просто создать новый архиватор с ключами, выполнить цикл по всем ключам и заархивировать его.

Вы также можете получить метод -attributeKeys любого класса, чтобы получить все ключи, а затем, возможно, использовать этот код для имитации архива:

NSKeyedArchiver *archive = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeObject:object forKey:key];
for (NSString *key in object.attributeKeys) {
    [archive encodeObject:[object valueForKey:key] forKey:key];
}
[archive finishEncoding];

В момент переноса данных в NSKeyedArchiver есть метод -setClass:forClassName:, и вы можете поддерживать все ваши старые ключи в новом объекте для преобразования их в различные свойства.

...