如何部分模拟外部对象

时间:2015-06-02 23:01:09

标签: ios objective-c unit-testing bdd ocmock

我有使用依赖对象(Keys对象)测试的类方法

APIRouter.m

+ (NSURL*)apiURLWithPath:(NSString*)path {
    MyKeys *keys = [MyKeys new];
    NSString *url = [NSString stringWithFormat:@"%@?api_key=%@", path, [keys APIKey]];
    return [NSURL URLWithString:url];
}

我试图部分模拟这个Keys对象并返回“MY_API_KEY”值,但测试方法失败并返回真正的API密钥(例如as78d687as6d7das8da)。

APIRouterSpec.m

describe(@"APIRouter", ^{
    it(@"should return url for api", ^{
        Keys *keys = [Keys new];
        id keysPartialMock = OCMPartialMock(keys);
        OCMStub([keysPartialMock APIKey]).andReturn(@"MY_API_KEY");
        NSURL *url = [APIRouter apiURLWithPath:@"http://www.api.com/v1/events"];
        expect([url absoluteString]).to.equal([NSString stringWithFormat:@"http://www.api.com/v1/events?api_key=MY_API_KEY"]);
    });
});

1 个答案:

答案 0 :(得分:2)

也许这对你有用:

在测试方法之外的某处:

static NSString *gMockApiKey = @"MY_API_KEY";

将这样的方法存根:

OCMStub([keysPartialMock APIKey]).andDo(^(NSInvocation *invocation)
{
    [invocation setReturnValue:&gMockApiKey];
});

修改

由于APIRouter可能正在使用自己的Keys实例,因此您可以尝试使用类模拟:

id keysMock = OCMClassMock([Keys class]);
OCMStub(ClassMethod([keysMock APIKey])).andDo(^(NSInvocation *invocation)
{
    [invocation setReturnValue:&gMockApiKey];
});

<强> EDIT2:

所以..我认为模拟它的正确方法是创建一个Keys的模拟实例。

位于测试文件顶部的某处:

static Keys *gMockedKeys = nil;
static NSString *gMockApiKey = @"MY_API_KEY";

设定:

- (void)setUp {

    [super setUp];

    gMockedKeys = [Keys new];

    id keysPartialMock = OCMPartialMock(gMockedKeys);
    OCMStub([keysPartialMock APIKey]).andDo(^(NSInvocation *invocation)
    {
        [invocation setReturnValue:&gMockApiKey];
    });
}

试验:

- (void)testAPIURLWithPath {

    id keysMock = OCMClassMock([Keys class]);
    OCMStub([keysMock new]).andReturn(gMockedKeys);

    NSURL *url = [APIRouter apiURLWithPath:@"http://www.api.com/v1/events"];
    NSString *expectedUrlString = [url absoluteString];
    XCTAssertEqualObjects(expectedUrlString, @"http://www.api.com/v1/events?api_key=MY_API_KEY", @"It Should work now..");
}