【问题标题】:Issue with OCMock 2.2.1, Xcode 5.0.2, XCTest and mocking of class methods (declared in a category)OCMock 2.2.1、Xcode 5.0.2、XCTest 和类方法模拟(在类别中声明)的问题
【发布时间】:2013-12-04 10:34:39
【问题描述】:

简介:

我有这个问题标题中提到的工具 (Xcode 5.0.2)、库 (OCMock 2.2.1) 和测试 (XCTest) 设置。

类别:

我在 NSObject 上有一个类别,其类方法如下:

+ (BOOL) hasDeclaredPropertyWithName: (NSString*) property;

OCMock 和 XCTest 框架有问题吗?:

现在我有一个简单的测试设置,我在其中模拟一个简单的值对象,如下所示: (我知道,模拟值对象是一种测试气味。但这仅用于说明目的。)

- (void) testFoo {
     id mock = [OCMockObject mockForClass: [TestObject class]];
     [[[mock stub] andReturn: NO] hasDeclaredPropertyWithName: @"propertyX"];
     [mock hasDeclaredPropertyWithName: @"propertyX"];
}

当执行测试方法 testFoo 的第 3 行时,我得到了错误:

-[NSProxy doesNotRecognizeSelector:hasDeclaredPropertyWithName:] called!

问题:

为什么使用 OCMock 模拟类方法似乎是不可能的(至少在我的设置中)?

如果我将hasDeclaredPropertyWithName 设置为像

这样的实例方法
- (BOOL) hasDeclaredPropertyWithName: (NSString*) property;

一切正常!

有人可以向我解释这种 OCMock 缺陷吗? 还是我在这里对 Objective-C 有一个重大的误解? :)

该类别是否可能会给运行时和/或 OCMock 带来麻烦? 顺便说一句,我没有直接在TestObject 中使用类方法尝试这个测试!

【问题讨论】:

  • 一个问题是您不能使用 andReturn 返回原语。这样做:andReturnValue:OCMOCK_VALUE((BOOL){NO}) 看看是否有帮助。
  • Ben,感谢您提供更多信息 - 很高兴知道。不幸的是,它没有帮助。

标签: objective-c unit-testing xcode5 ocmock xctest


【解决方案1】:

好的,首先是基本情况,我们正在模拟一个类别类方法:

我为了测试而准备的一些课程,Huzzah:

@interface Huzzah : NSObject
+ (void)doClass;
+ (void)doClass2;
+ (void)doClass3;
- (void)doInstance;
@end

我创建了一个类别:

@interface Huzzah (Cat)
+ (BOOL)hasX:(NSString *)x;
@end

@implementation Huzzah (Cat)
+ (BOOL)hasX:(NSString *)x
{
    return YES;
}
@end

在我的测试中:

#import "Huzzah+Cat.h"
- (void)testHuzzahCat
{
    id mock = [OCMockObject mockForClass:Huzzah.class];
    [[[mock stub] andReturnValue:OCMOCK_VALUE((BOOL){NO})] hasX:OCMOCK_ANY];
    NSLog(@"hasX: %i", [Huzzah hasX:@"DoYouHas?"]);
}

输出:hasX: 0

现在让我们在 NSObject 上尝试一个类别:

@interface NSObject (Cat)
+ (BOOL)hasY:(NSString *)y;
@end

@implementation NSObject (Cat)
+ (BOOL)hasY:(NSString *)y
{
    return YES;
}
@end

我们的新测试:

#import "NSObject+Cat.h"
- (void)testObjectCat
{
    id mock = [OCMockObject mockForClass:Huzzah.class];
    [[[mock stub] andReturnValue:OCMOCK_VALUE((BOOL){NO})] hasY:OCMOCK_ANY];
    NSLog(@"hasY: %i", [Huzzah hasY:@"DoYouHas?"]);
}

结果:hasY: 0

是否有可能类别的实现没有编译到您的项目中?

【讨论】:

  • 请注意,我使用的是 SenTestingKit,而不是 XCTest。不确定这是否会有所不同。
  • 好的,你的例子帮助我理解了我真正想要做什么。感谢那!你能解释我一件事吗?为什么我不能执行以下操作:NSLog(@"hasX: %i", [[mock stub] hasX:@"DoYouHas?"]);NSLog(@"hasY: %i", [Huzzah hasY:@"DoYouHas?"]);?这实际上就是我试图通过我的示例[mock hasDeclaredPropertyWithName: @"propertyX"]; 来说明的内容。 OCMockObject 派生自 NSProxy,大概就是这个原因。
  • @NenadM [[mock stub] hasX:@"DoYouHas?"] 将返回一个 OCMockObject 类型的匿名对象,该对象将返回 nil(因为您没有声明返回值)。在NSLog 之后,该对象将立即超出范围,并且不再模拟类方法。你的第二个例子是我在回答中使用的......这是一个错字吗?我们在存根之后调用类方法。我们可以在不存根的情况下调用它,它会返回 1。
  • 对不起,这是一个错字!我的意思是:NSLog(@"hasY: %i", [[mock stub] hasY:@"DoYouHas?"]); 关于你的例子。
  • 好的,只要你明白你建议的方法返回 OCMockObjects 而不是整数,我认为你很高兴。查看 OCMock 功能页面:ocmock.org/features
猜你喜欢
  • 2023-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-12
  • 1970-01-01
  • 2014-02-14
相关资源
最近更新 更多