Kiwi iOS上下文块的奇怪排序

我有一个看起来像这样的Kiwi spec文件:

#import "Kiwi.h" #import "MyCollection.h" SPEC_BEGIN(CollectionSpec) describe(@"Collection starting with no objects", ^{ MyCollection *collection = [MyCollection new]; context(@"then adding 1 object", ^{ MyObject *object = [MyObject new]; [collection addObject:object]; it(@"has 1 object", ^{ [collection shouldNotBeNil]; [collection.objects shouldNotBeNil]; [[theValue(collection.objects.count) should] equal:theValue(1)]; //failing test }); context(@"then removing 1 object", ^{ [collection removeObject:object]; it(@"has 0 objects", ^{ [[theValue(collection.objects.count) should] equal:theValue(0)]; //passing test }); }); }); }); SPEC_END 

运行规范导致这行代码[[theValue(collection.objects.count) should] equal:theValue(1)];一次失败[[theValue(collection.objects.count) should] equal:theValue(1)];

这是奇怪的部分 – 如果我删除整个context(@"then removing 1 object", ^{...})阻止规范上述测试通过。

这使我相信[collection removeObject:object]行在失败的测试之前执行。 我有一种感觉,我可能误解了执行块的顺序。

任何建议,将不胜感激!

你认为[collection removeObject:object]在失败的测试之前执行是正确的。 将Kiwi测试视为两次操作:

  1. 设置:测试文件中的代码从上到下执行,以设置测试上下文和期望
  2. 执行:每个unit testing运行,基本上每个/ specify语句一个,每个测试重复正确的设置/拆除代码

请注意,Kiwi测试文件中的大多数代码都被指定为发送到Kiwi函数的一系列块。 任何不遵循Kiwi块模式的代码,例如初始化/修改collection变量的代码,都可能因此在意外时间执行。 在这种情况下,在设置测试时,第一次传递期间正在执行所有集合修改代码, 然后运行测试。

使用__block修饰符声明collection ,并使用beforeEach实例化和修改collection对象:

 describe(@"Collection starting with no objects", ^{ __block MyCollection *collection; beforeEach(^{ collection = [MyCollection new]; }); context(@"then adding 1 object", ^{ beforeEach(^{ MyObject *object = [MyObject new]; [collection addObject:object]; }); it(@"has 1 object", ^{ ... }); context(@"then removing 1 object", ^{ beforeEach(^{ [collection removeObject:object]; }); it(@"has 0 objects", ^{ ... 

beforeEach块告诉Kiwi每unit testing专门运行给定的代码一次,并且对于嵌套的上下文,块将根据需要按顺序执行。 所以Kiwi会做这样的事情:

 // run beforeEach "Collection starting with no objects" collection = [MyCollection new] // run beforeEach "then adding 1 object" MyObject *object = [MyObject new] [collection addObject:object] // execute test "has 1 object" [collection shouldNotBeNil] [collection.objects shouldNotBeNil] [[theValue(collection.objects.count) should] equal:theValue(1)] // run beforeEach "Collection starting with no objects" collection = [MyCollection new] // run beforeEach "then adding 1 object" MyObject *object = [MyObject new] [collection addObject:object] // run beforeEach "then removing 1 object" [collection removeObject:object] // execute test "has 0 objects" [[theValue(collection.objects.count) should] equal:theValue(0)] 

__block修饰符将确保可以通过所有这些块函数正确保留和修改collection对象引用。