简体   繁体   English

如何对NSCoding进行单元测试?

[英]How to unit test NSCoding?

I have an iOS application with data persisted using NSCoding and more precisely NSKeyedArchiver. 我有一个iOS应用程序,使用NSCoding持久化数据,更确切地说是NSKeyedArchiver。 This application is already available on the App Store. 此应用程序已在App Store上提供。

I'm working on version 2 of the application and the data model should change. 我正在研究应用程序的第2版,数据模型应该改变。 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. 问题是,MyDataModelObject可能会在应用程序的版本2中重新计算甚至删除。 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 ? 有没有办法模拟在不使用这个类的类的encodeWithCoder:方法中完成的操作?


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");
}

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. 您可以使用您在旧类中使用的键/值来预加载NSDictionary的实例,只需创建一个新的键控归档器,循环遍历所有键并将其归档。

You can also get any class's -attributeKeys method to get all the keys and then possibly use this code to simulate an archive: 您还可以获取任何类的-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];

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. 在迁移数据时,NSKeyedArchiver具有方法-setClass:forClassName:并且您可以支持新对象中的所有旧键将它们转换为不同的属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM