首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具有核心数据/生成器的OCMock引发异常NSInvalidArgumentException [NSProxy doesNotRecognizeSelector]

具有核心数据/生成器的OCMock引发异常NSInvalidArgumentException [NSProxy doesNotRecognizeSelector]
EN

Stack Overflow用户
提问于 2012-10-03 03:36:40
回答 1查看 1.8K关注 0票数 1

我在单元测试中使用OCMock模拟NSManagedObjects。我使用Mogenerator为我的核心数据对象生成机器和人类可读的文件。我正在尝试模拟一个NSManagedObject来返回一个布尔值和一个字符串。这两个都是我的核心数据实体的属性。当我模拟BOOL时,从对象返回的值是正确的,我的类使用它,并且测试成功通过。当我试图存根同一对象上的NSString属性时,它抛出一个NSInvalidArgumentException [NSProxy doesNotRecognizeSelector]

下面是调用代码:

代码语言:javascript
复制
id biller = [OCMockObject mockForClass:[Biller class]];
// passes
[[[biller stub] andReturnValue:OCMOCK_VALUE((BOOL){NO})] billerValidatedValue];
// throws exception
[[[biller stub] andReturn:@"Test"] name];

以下是例外情况:

代码语言:javascript
复制
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSProxy doesNotRecognizeSelector:name] called!'

我知道有一些some recommendations为了测试的目的在NSManagedObject前面有一个接口,但这似乎在Mogenerator机器/人类文件之上增加了复杂性。

在不完全重新配置这段代码的情况下,还有没有其他建议?这段代码已经投入生产,我们正在尝试在开发新功能时添加单元测试。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-10-03 07:28:20

问题的症结在于您的核心数据模型在测试中不可用,因此当您尝试存根属性读取时,该方法并不存在。核心数据在运行时动态截获属性访问器。

要使您的模型可用,您需要确保您的.xcdatamodeld包含在您的单元测试目标中,并且您需要在测试中设置模型。我不确定您是否能够模拟动态属性,但在测试中对核心数据对象执行CRUD操作变得微不足道,因此没有必要模拟它们。以下是在测试中初始化模型的一种方法:

代码语言:javascript
复制
static NSManagedObjectModel *model;
static NSPersistentStoreCoordinator *coordinator;
static NSManagedObjectContext *context;
static NSPersistentStore *store;

-(void)setUp {
    [super setUp];
    if (model == nil) {
        @try {
            NSString *modelPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"my-model" ofType:@"mom"];
            NSURL *momURL = [NSURL fileURLWithPath:modelPath];
            model = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURL];
        }
        @catch (NSException *exception) {
            NSLog(@"couldn't get model from bundle: %@", [exception reason]);
            @throw exception;
        }
    }
    coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
    NSError *error;
    store = [coordinator addPersistentStoreWithType: NSInMemoryStoreType
                                      configuration: nil
                                                URL: nil
                                            options: nil
                                              error: &error];
    assertThat(store, isNot(nil));
    context = [[NSManagedObjectContext alloc] init];
    [context setPersistentStoreCoordinator:coordinator];
}

-(void)tearDown {
    // these assertions ensure the test was not short-circuited by a failure to initialize the model
    assertThat(model, isNot(nil));
    assertThat(context, isNot(nil));
    assertThat(store, isNot(nil));
    assertThat(coordinator, isNot(nil));
    NSError *error = nil;
    STAssertTrue([coordinator removePersistentStore:store error:&error],
                 @"couldn't remove persistent store: %@", [error userInfo]);
    [super tearDown];
}

或者,您可以通过使用MagicalRecord来显著简化工作。即使你不在你的应用中使用它,你也可以在你的测试中使用它来封装所有的核心数据设置。下面是我们在使用MagicalRecord的应用程序中的单元测试设置:

代码语言:javascript
复制
-(void)setUp {
    [super setUp];
    [MagicalRecordHelpers setupCoreDataStackWithInMemoryStore];
}

-(void)tearDown {
    [MagicalRecordHelpers cleanUp];
    [super tearDown];
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12697058

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档