用于OC Mockito模拟验证的自定义Hamcrest匹配器

时间:2013-01-18 04:18:41

标签: ios unit-testing tdd ocmockito ochamcrest

我正在使用OCHamcrest和OCMockito对iOS项目进行单元测试。我正在努力使用自定义匹配器来理解使用参数的方法期望的模拟验证。特别是,我想验证传递给期望方法的参数之一,但我需要拉开传递的参数才能这样做。为了演示,这是我的测试方法的相关部分:

EAAccessory *accessory = mock([EAAccessory class]);
UIViewController <ZKSearchManagerDelegate> *mockController = 
    mockObjectAndProtocol(
        [UIViewController class], @protocol(ZKSearchManagerDelegate)
    );
[verify(mockController) 
        zkZSensorFound:isSensorWithAccessory(accessory) 
     fromSearchManager:_sm];

-zkZSensorFound:fromSearchManager:将包含EAAccessory的对象作为属性。在我的自定义匹配器中,我需要打开该对象并检查该属性,以确保它与此测试方法中的accessory相同。我可以很容易地将accessory传递给匹配器,但是如何获取传递给参数的实际对象以便在我的匹配器中使用?或者,我是否认为这一切都错了?

更新

我已经接受了@JonReid的回答,因为它比我编造的解决方案更优雅。不过,我认为我所使用的(感谢{3}}博客文章)在其他地方可能会有用:

#import "ArgumentCaptor.h"

EAAccessory *accessory = mock([EAAccessory class]);
UIViewController <ZKSearchManagerDelegate> *mockController = 
    mockObjectAndProtocol(
        [UIViewController class], @protocol(ZKSearchManagerDelegate)
    );
ArgumentCaptor *captor = argCaptor();
[verify(_mockController) zkZSensorFound:(ZKZSensor *)captor 
                      fromSearchManager:is(sameInstance(_sm))];
ZKZSensor *sensor = captor.argument;
assertThat(sensor.accessory, is(_mockAccessory));

1 个答案:

答案 0 :(得分:1)

首先,请注意,当您未向OCMockito指定匹配器时,它会使用isEqual匹配器。这可能不是您要为第二个参数验证的内容。我会检查身份:

fromSearchManager:sameInstance(_sm)

如果输入参数,则会抱怨匹配器sameInstance不是搜索管理器。解决方法是强制使用匹配器删除输入:

fromSearchManager:(id)sameInstance(_sm)

现在为第一个参数:您可能根本不需要创建自定义匹配器。如果您只想检查属性值,请使用hasProperty。假设该属性名为accessory

zkZSensorFound:(id)hasProperty(@"accessory", sameInstance(accessory))

全部放在一起:

[verify(mockController) 
        zkZSensorFound:(id)hasProperty(@"accessory", sameInstance(accessory)) 
     fromSearchManager:(id)sameInstance(_sm)];