OCMStub在创建存根时将OCMConstraint实例发送到实际方法

时间:2014-11-24 11:05:50

标签: objective-c unit-testing ocmock

我尝试使用OCMock从REST客户端类(或将来)测试针对请求的URL /路径。客户端使用RestKit(使用AFNetworking)进行通信。 因此,我的计划是:

  1. 创建一个块,检查AFHTTPRequestOperation网址是否为所需网址。
  2. 创建AFHTTPClient
  3. 的部分模拟
  4. 使用块(1)模拟(存根)enqueueHTTPRequestOperation:方法。
  5. 创建RKObjectManager的模拟并将其HTTPClient属性设置为。{ AFHTTPClient部分模拟(2。)。
  6. 使用模拟管理器(来自4。)初始化我的客户端类的实例。
  7. 调用要检查URL的此实例的方法。
  8. 验证是否已调用enqueueHTTPRequestOperation:
  9. 我不确定我是否错误地认为OCMock是错误的,因为我找不到像我需要的那样采用一个或多个参数的模拟方法的示例。 ......从来没有,这就是我试图实现目标的方式:

        void (^checkBlock)(NSInvocation *) = ^(NSInvocation *invocation) {
    
            AFHTTPRequestOperation *requestOperation = nil;
            [invocation getArgument:&requestOperation atIndex:0];
    
            XCTAssert(requestOperation != nil);
    
            NSString *path = requestOperation.request.URL.path;
            XCTAssert([path containsString:@"/rest/user/authenticate"]);
        };
    
        AFHTTPClient *httpClientMock = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:FAServerUrl]];
        OCMPartialMock(httpClientMock);
    
        [OCMStub([httpClientMock enqueueHTTPRequestOperation:[OCMArg isNotNil]]) andDo:checkBlock];
    
        RKObjectManager *objectManager = OCMClassMock([RKObjectManager class]);
    
        [OCMStub([objectManager HTTPClient]) andReturn:httpClientMock];
    
        FAUserClient *userClient = [[FAUserClient alloc] initWithUser:nil objectManager:objectManager];
    
        [userClient getAccessTokenForUsername:@"testuser"
                                     password:@"pass123"
                                      success:^(NSString *token, NSArray *roles) {
                                      }
                                      failure:^(NSInteger errorCode, NSError *error) {                                          
                                      }];
    
        OCMVerify([httpClientMock enqueueHTTPRequestOperation:OCMOCK_ANY]);
    

    但在[OCMStub([httpClientMock enqueueHTTPRequestOperation:[OCMArg isNotNil]]) andDo:checkBlock];我得到一个EXC_BAD_ACCESS(代码= 1)。 显然,创建模拟存根(使用OCMStub)会使用给定的[OCMArg isNotNil]调用存根方法。我认为A:参数只具有声明性意义而B:这会创建一个存根,并且不会立即调用该方法。

    任何有关"权利"的任何帮助或建议方向将不胜感激。

    修改

    经过尝试:

        OCMStub([httpClientMock enqueueHTTPRequestOperation:[OCMArg checkWithBlock:^BOOL(id obj) {
            AFHTTPRequestOperation *request = (AFHTTPRequestOperation *)obj;
            NSString *path = request.request.URL.path;
            XCTAssert([path containsString:@"/rest/user/authenticate"]);
            return YES;
        }]]);
    

    ...使用相同的"结果"。

    最佳, 加布里埃尔

1 个答案:

答案 0 :(得分:1)

修改

仔细观察。您正在呼叫OCMPartialMock(httpClientMock)。这不会转换您调用它的对象,它返回部分模拟。捕获变量中的结果。

AFHTTPClient *httpClientMock = OCPartialMock([[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:FAServerUrl]]);

您仍应在andDo:块中进行以下更改。您还可以使用“现代”语法:

OCMStub([myObject myMethod]).andDo(myBlock);

<强>原始

我认为问题可能是andDo:块中的代码。

[invocation getArgument:&requestOperation atIndex:0];

对于所有Objective-C方法,NSInvocation在索引0和1处有两个默认参数self_cmd。尝试在索引2处获取参数。

您可能还会考虑包含NSInvocation + OCMAdditions,它们会为您提供getArgumentAtIndexAsObject。另一种方法是使用[OCMArg checkWithBlock:],其中arg直接传递给您的评估块。