OCMock:做一个存根做一些事情

时间:2009-01-27 15:14:43

标签: objective-c cocoa cocoa-touch

我已经习惯了OCMock。来自Java / JMock背景我现在正在寻找能够说[[[myMock stub] returnValueFromCustomMethod] someMockedMethod];在测试类中定义returnValueFromCustomMethod的能力。我原本在考虑[[[myMock stub] usingSelector:@selector(myMethod:)] someMockedMethod];的条款,但写完后我想知道我的第一种方法是否更有意义。无论哪种方式,有人可以告诉我是否以及如何做到这一点?

1 个答案:

答案 0 :(得分:0)

我的原始答案偏离了轨道:OCMock不支持这个!如果你想改变OCMock来支持这一点,你需要做一些事情,比如在OCMockRecorder中添加一个BOOL returnValueIsFromInvocation字段,并添加一个方法来设置它:

- (id)andReturnResultOfInvocation:(NSInvocation *)anInvocation {
  returnValueIsFromInvocation = YES;
  returnValueIsBoxed = NO;
  returnValueShouldBeThrown = NO;
  [returnValue autorelease];
  returnValue = [anInvocation retain];
  return self;
}

然后教setUpReturnValue调用调用(更改以粗体显示):

- (void)setUpReturnValue:(NSInvocation *)anInvocation
{
  if (returnValueIsFromInvocation) {
    NSInvocation *returnValueInvocation = (NSInvocation *)returnValue;
    [returnValueInvocation invoke];
    void *buffer = malloc([[anInvocation methodSignature] methodReturnLength]);
    [returnValueInvocation getValue:buffer];
    [anInvocation setReturnValue:buffer];
    free(buffer);
  }
  else if(returnValueShouldBeThrown)
  {
    @throw returnValue;
  }
  else if(returnValueIsBoxed)
  {
    if(strcmp([[anInvocation methodSignature] methodReturnType],
              [(NSValue *)returnValue objCType]) != 0)
      [NSException raise:NSInvalidArgumentException
                  format:@"Return value does not match method signature."];
    void *buffer = malloc([[anInvocation methodSignature] methodReturnLength]);
    [returnValue getValue:buffer];
    [anInvocation setReturnValue:buffer];
    free(buffer);
  }
  else
  {
    const char *returnType = [[anInvocation methodSignature] methodReturnType];
    const char *returnTypeWithoutQualifiers = returnType + (strlen(returnType) - 1);
    if(strcmp(returnTypeWithoutQualifiers, @encode(id)) == 0)
      [anInvocation setReturnValue:&returnValue];   
  }
}

通过引入子类很难做到这一点,因为你必须覆盖返回OCMockRecorders的方法(如stubexpect等),但是OCMockObject的具体子类(OCClassMockObject和OCProtocolMockObject)被框架隐藏。