(void)testAddConfig
{
[UMNavigationController setViewControllerName:@"ViewControllerA" forURL:@"
um://viewa2"];
NSMutableDictionary *config = [UMNavigationController config];
NSLog(@"%@", [config allKeys]);
HC_assertThat([config allKeys],
HC_containsInAnyOrder(HC_equalTo(@"um://viewa2"), HC_equalTo(@"
um://viewa"),
HC_equalTo(@"um://viewb"), nil));
GHAssertEqualStrings(config[@"um://viewa2"], @"ViewControllerA",
@"config set error.");
}

  代码8,AddConfig用例
  自建匹配规则
  上述例子表明匹配规则往往无法恰好满足测试需求,需要对默认规则进行升级。
  升级一个匹配规则,首先阅读OCHamcrest默认规则源码,找到无法满足需求的代码。上述HC_containsInAnyOrder的例子中,个性需求是某个collection是否包含某几个元素(而非完整集合),而默认规则只能匹配完整集合。阅读源码(代码9)可以发现,在maches:describingMismatchTo:函数中,对规则对象的collection属性(要进行匹配的容器对象)进行遍历,并逐个调用matches:方法。matches:方法中针对每个collection属性中的元素遍历匹配规则集合(matchers),并从规则集合(matchers)中移除匹配成功的规则。当给出的规则集合(matchers)全部成功匹配过之后,matchers属性已经为空。若此时对collection属性的遍历继续进行,matches:方法不会进入匹配逻辑,直接跳出循环返回NO,导致匹配失败。

 

(BOOL)matches:(id)item
{
NSUInteger index = 0;
for (id matcher in matchers)
{
if ([matcher matches:item])
{
[matchers removeObjectAtIndex:index];
return YES;
}
++index;
}
[[mismatchDescription appendText:@"not matched: "] appendDescriptionOf:item];
return NO;
}
- (BOOL)matches:(id)collection describingMismatchTo:(id)
mismatchDescription
{
if (![collection conformsToProtocol:@protocol(NSFastEnumeration)])
{
[super describeMismatchOf:collection to:mismatchDescription];
return NO;
}
HCMatchingInAnyOrder *matchSequence =
[[HCMatchingInAnyOrder alloc] initWithMatchers:matchers
mismatchDescription:mismatchDescription];
for (id item in collection)
if (![matchSequence matches:item])
return NO;
return [matchSequence isFinishedWith:collection];
}

  代码9,HC_containsInAnyOrder规则中的两个核心方法
  我们的需求是,当匹配规则列表全部成功匹配之后是此次匹配成功的标志。所以需要修改matches:方法中的匹配逻辑,当匹配列表为空则返回YES。
  升级方案是继承HCIsCollectionContainingInAnyOrder创建一个新的匹配规则类HCIsCollectionHavingInAnyOrder;重新定义匹配规则HC_hasInAnyOrder;重写调用matches:方法的matches:describingMismatchTo:方法(代码10);更新的核心是定义一个HCMatchingInAnyOrderEx类,按照个性需求定义matches:方法(代码11)。使用这个修改过的匹配规则可以判断一个Collection是否包含某个几个元素了。