How to unit test NSCoding?

元气小坏坏 提交于 2019-12-10 13:23:44

问题


I have an iOS application with data persisted using NSCoding and more precisely NSKeyedArchiver. This application is already available on the App Store.

I'm working on version 2 of the application and the data model should change. So I need to handle data model migration. I want it covered by unit tests.

In my tests, I want to dynamically generate persisted data with old data model, launch migration and see if everything went well.

Currently, archiving an object looks like this :

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

The problem is, MyDataModelObject might be re-factored or even deleted in the version 2 of the application. So I can't use this class in my tests to generate an 'old version archive'.

Is there a way to simulate what is done in the encodeWithCoder: method of a class without using this class ?


What I would like to achieve is the following

- 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:


I don't really understand your question so I will give you two answers:

You can preload an instance of NSDictionary with keys/values you would use with your old class and just create a new keyed archiver, loop through all the keys and archive it.

You can also get any class's -attributeKeys method to get all the keys and then possibly use this code to simulate an archive:

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];

On the point of migrating data, NSKeyedArchiver has the method -setClass:forClassName: and you can support all of your old keys in your new object to translate them into different properties.



来源:https://stackoverflow.com/questions/8267004/how-to-unit-test-nscoding

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!