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测试视为两次操作:
- 设置:测试文件中的代码从上到下执行,以设置测试上下文和期望
- 执行:每个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
对象引用。