How to unit test NSCoding?

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

I am working on version 2 of the application and the data model needs to change. Therefore, I need to handle the migration of the data model. I want it covered by unit tests.

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

Currently, archiving an object is as follows:

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

The problem is that MyDataModelObject can be reinstalled or even removed in version 2 of the application. Therefore, I cannot use this class in my tests to create an "old version archive".

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


I would like to get 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 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"); } 
+6
source share
1 answer

I do not understand your question, so I will give you two answers:

You can preload the NSDictionary instance with the keys / values ​​that you would use with the old class, and simply create a new archiver key, skip all the keys and archive it.

You can also get any method of the -attributeKeys class to get all the keys, and then maybe 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]; 

At the time of data transfer, NSKeyedArchiver has the -setClass:forClassName: method, and you can maintain all your old keys in a new object until you transfer them to different properties.

+1
source

Source: https://habr.com/ru/post/902374/


All Articles