我非常喜欢高度可预测的Arrange Act Assert format单元测试。
因为Kiwi没有针对模拟的明确验证声明,它会强制使用不同的模式,例如:
// Arrange
Thing *mockThing = [CollaboratingClass mock];
TestedClass *sut = [[TestedClass alloc] initWithCollaborator:mockThing];
// Expect (collaboration expectations)
[[[mockThing should] receive] someMessage];
// Act
[mockArray someMethodInvolvingCollaborator];
// Assert (state expectations)
[[sut.someProperty should] equal:someValue];
我知道无论如何都会进行验证,但更喜欢能够快速扫描测试,并将断言和期望放在一个可预测的位置。这由mockito(及其Objective-C实现OCMockito)很好地启用,其中验证步骤指定事后调用方法,使得先前的期望步骤不必要。
我是新手的相对新手,所以我可能错过了文档中的内容。有没有办法明确核实猕猴桃嘲笑?
答案 0 :(得分:4)
您提供的关于 Arrange Act Assert 的链接可以说明该模式的好处(强调添加):
优点:
- ...
- 使一些TestSmells更加明显:
- 断言与“Act”代码混杂在一起。
- 尝试一次测试太多不同内容的测试方法
特别是如果您的目标是能够快速扫描断言,我认为您的示例最好分为两个测试用例:协作测试,以及对象状态如何变化的单独测试。
我实际上认为这里有第四步,特别是协作测试,即 Expect 。 Kiwi允许您安排,期待,行动,其中OCMock
实际上要求您通过要求[mockThing verify]
添加第四个冗余的断言步骤。
我认为这是设置这些测试的更好方法:
__block TestedClass *sut;
beforeAll(^{
sut = [[TestedClass alloc] initWithCollaborator:mockThing];
}
// Collaboration: Arrange, Expect, Act
it(@"sends someMessage to mockThing", ^{
// Arrange
Thing *mockThing = [CollaboratingClass mock];
// Expect
[[[mockThing should] receive] someMessage];
// Act
[mockArray someMethodInvolvingCollaborator];
}
// State: Arrange, Act, Assert
it(@"sets someProperty to the return value of someMethod", ^{
// Arrange
NSString *expectedString = @"foo";
Thing *mockThing = [CollaboratingClass mock];
[[mockThing stubAndReturn:expectedString] someMessage];
// Act
[mockArray someMethodInvolvingCollaborator];
// Assert
[[sut.someProperty should] equal:expectedString];
}
此设置带来的好处是,如果您需要基于协作者返回值的分支,您可以添加另一个测试,其中存根someMethod
以返回不同的结果,并使其不同断言:
it(@"sets someProperty to nil if someMethod returns baz", ^{
// Arrange
Thing *mockThing = [CollaboratingClass mock];
[[mockThing stubAndReturn:@"baz"] someMessage];
// Act
[mockArray someMethodInvolvingCollaborator];
// Assert
[sut.someProperty shouldBeNil];
}
最终,我认为Kiwi不需要我们verify
我们的测试双打,帮助我们。