从框架项目进行单元测试时应用程序崩溃

Posted

技术标签:

【中文标题】从框架项目进行单元测试时应用程序崩溃【英文标题】:Application crashes while doing unit testing from framework project 【发布时间】:2016-08-25 11:15:17 【问题描述】:

我创建了一个框架项目来包含我的应用程序的所有业务逻辑。这样,核心数据模型也转移到了框架项目中。现在我有几个 XCTestCase 类来对框架中的管理器和模块类进行单元测试。这些类具有核心数据操作。因此,在单元测试期间,这些类是指 DBManager 类。在这种情况下,我会崩溃,发生在创建持久模型时。同时,当我在主项目中使用相同的单元测试用例时,一切正常。我主要注意到的一点是,在运行主项目和单元测试用例时,持久创建时创建的 storeURL 是不同的框架。以下是创建的 storeURL。 file:///Users/Gowtham/Library/Developer/CoreSimulator/Devices/F7DB4F9B-D323-4978-A816-B5363F26BE32/data/Containers/Data/Application/92F08534-F5AD-4B4B-B1A3-D3CEF17758C0/Documents/ IHA.sqlite [主项目]

file:///Users/Gowtham/Library/Developer/CoreSimulator/Devices/F7DB4F9B-D323-4978-A816-B5363F26BE32/data/Documents/IHA.sqlite [框架项目中的单元测试用例]

以下是控制台中显示的异常。

未解决的错误 Error Domain=YOUR_ERROR_DOMAIN Code=9999 “无法初始化应用程序保存的数据” UserInfo=NSLocalizedDescription=初始化失败 应用程序保存的数据,NSUnderlyingError=0x7be93420 Error 域=NSCocoaErrorDomain 代码=134100 "(null)" UserInfo=metadata= NSPersistenceFrameworkVersion = 641; NSStoreModelVersionHashes = 用户字典条目 = ; ; NSStoreModelVersionHashesVersion = 3; NSStoreModelVersionIdentifiers = ( “” ); NSStoreType = SQLite; NSStoreUUID = "6C70A93B-39DD-4357-A0C2-0BDA5DF51E32"; "_NSAutoVacuumLevel" = 2; , reason=开店的型号和开店的型号不兼容, NSLocalizedFailureReason=创建或加载 应用程序保存的数据。, NSLocalizedDescription = "初始化应用保存数据失败"; NSLocalizedFailureReason = "创建或加载应用程序保存的数据时出错。"; NSUnderlyingError = "错误域=NSCocoaErrorDomain 代码=134100 \"(null)\" UserInfo=metadata=\n NSPersistenceFrameworkVersion = 641;\n NSStoreModelVersionHashes = \n UserDictionaryEntry = ;\n ;\n NSStoreModelVersionHashesVersion = 3;\n NSStoreModelVersionIdentifiers = (\n \"\"\n );\n NSStoreType = SQLite;\n NSStoreUUID = \"6C70A93B-39DD-4357-A0C2-0BDA5DF51E32\";\n \"_NSAutoVacuumLevel\" = 2;\n, reason=开店的型号和开店的型号不兼容";

谁能给我关于编写与框架项目中的核心数据通信的单元测试用例的正确方法的建议?

崩溃发生在 DatabaseManager 类的以下方法中:

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator 
// The persistent store coordinator for the application. This implementation creates and returns a coordinator, having added the store for the application to it.
if (_persistentStoreCoordinator != nil) 
    return _persistentStoreCoordinator;


// Create the coordinator and store

_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"IHA.sqlite"];
NSError *error = nil;
NSString *failureReason = @"There was an error creating or loading the application's saved data.";
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) 
    // Report any error we got.
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    dict[NSLocalizedDescriptionKey] = @"Failed to initialize the application's saved data";
    dict[NSLocalizedFailureReasonErrorKey] = failureReason;
    dict[NSUnderlyingErrorKey] = error;
    error = [NSError errorWithDomain:@"YOUR_ERROR_DOMAIN" code:9999 userInfo:dict];
    // Replace this with code to handle the error appropriately.
    // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    abort();


return _persistentStoreCoordinator;

当应用程序与框架项目进行数据库操作通信时,它工作正常。同时,Framework项目中的XCTest Target调用DB操作时,发生了crash。请任何人提供有用的答案。

【问题讨论】:

【参考方案1】:
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator

    if (_persistentStoreCoordinator != nil)
    
        return _persistentStoreCoordinator;
    

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"IHA.sqlite"];

    NSMutableDictionary *options = [[NSMutableDictionary alloc] init];
    [options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
    [options setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];

    NSError *error = nil;
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error])
    
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    

    return _persistentStoreCoordinator;

【讨论】:

【参考方案2】:

感谢您提出的建议。最后我发现了很简单的原因。即使我已经从模拟器中删除了该应用程序,之前在以下路径中创建的 sqlite 文件的引用也没有被清除。然后我手动转到该路径并删除了生成的旧 sqlite 文件。然后一切正常。如果有人遇到类似的问题,请检查从以下路径生成的旧 sqlite 文件。旧的 sqlite 和 xcdatamodel 中定义的结构不匹配。

/Users/...用户名.../Library/Developer/CoreSimulator/Devices/F7DB4F9B-D323-4978-A816-B5363F26BE32/data/Documents/appname.sqlite

F7DB4F9B-D323-4978-A816-B5363F26BE32 是保存与应用相关的所有数据的文件夹。

【讨论】:

以上是关于从框架项目进行单元测试时应用程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章

当 testes 函数调用 AppDelegate + managed Object 时单元测试崩溃

Xcode单元测试:尝试将测试数据从单元测试写入项目文件夹时权限被拒绝

如何在 intellij 中为播放框架应用程序运行单元测试

gtest变化量

颤振从单元\小部件测试调用http请求而不进行模拟

从自定义框架访问 Coredata 时应用程序崩溃