期望使用OCMock从非实例化变量进行方法调用

时间:2013-10-09 18:40:14

标签: ios objective-c xcode ocmock

我不确定这是否是最好的标题,但基本上我知道变量将在运行函数时实例化。我想对这个变量进行部分模拟,并期望在变量实例化之前进行某些方法调用。这是我正在尝试做的一个例子。

-(void)testMethod {
    id mockVar = [OCMock partialMockForObject:self.controller.variable];
    [[mockVar expect] someMethod];

    [self.controller method];
    [mockVar verify];
}

控制器内部的方法如下所示:

-(void)method {
    self.variable = [[Class alloc]init];
    [self.variable someMethod];
}

我收到的消息如'doesNotRecognizeSelector'。这可能吗?

2 个答案:

答案 0 :(得分:1)

这感觉就像一个奇怪的测试,但是如果你嘲笑访问器就可以了:

-(void)testMethod {
    id mockVar = [OCMock mockForClass:[Class class]];
    id mockController = [OCMock partialMockForObject:controller];
    [[[mockController stub] andReturn:mockVar] variable];
    [[mockVar expect] someMethod];

    [self.controller method];
    [mockVar verify];
}

如果你提供一个更具体的例子,你可以给你一个更好的答案。

答案 1 :(得分:1)

如果有可能存在属性访问者,我会继续这样做。但是如果你需要部分模拟实际代码实际创建的实例,那么它可能存在于属性上 - setter方法成为钩子 - 但它绝对是丑陋的。

基本思想是使用OCMArg的checkWithBlock:功能拦截set方法的参数,并在该点创建部分mock。您可以将其分配给块外的变量,以便稍后进行验证。它看起来像这样:

-(void)testMethod
{
    id mockController = [OCMockObject partialMockForObject:self.controller];
    __block id mockVar;

    [[[mockController stub] andForwardToRealObject] setVariable:[OCMArg checkWithBlock:^BOOL(id param) {
        mockVar = [OCMockObject partialMockForObject:param];
        [[mockVar expect] someMethod];
        return YES;
    }]];

    [self.controller method];  // mockVar will be created and assigned during this call
    [mockVar verify];
}

如果您的真实代码创建了一个对象并且只将其暂时存储在本地变量(而不是实例变量)中,除了重构您的实际代码以便更容易测试(例如移动)之外,您实际上无能为力将对象创建为新方法的代码,这使得存根更加容易。