我在ClassA中有这两种方法
-(IBAction)onSubmit;
-(void)validateName:(NSString*)name;
@implementation
- (IBAction)onSubmit {
[self validateName:self.textfield.text];
}
-(void)validateName:(NSString*)name{
// do something
}
我的测试如下所示:
//given
ClassA *classA = mock([ClassA class]);
classA.textfield.text = @"Foo";
// when
[classA onSubmit];
[verify(classA) validateName:@"Foo"];
但这不起作用,我一直在说:
Expected 1 matching invocation, but received 0
当调用onSubmit时,如何编写一个验证validateName是否被执行的测试。
答案 0 :(得分:5)
适当的单元测试测试内部状态和外部行为。您的单元测试正在测试 您的代码是否做了某些事情,而不是 它做了什么。状态验证会告诉您实现了预期的结果,而行为验证则告诉您协作对象正确地与您正在测试的系统进行交互。这允许你做重构之类的精彩事情。
对内部状态的测试如下:
鉴于初始状态,如果被测系统做某事,那么 结果状态应该是 this 。
对外部行为的测试如下:
如果受测试的系统做某事,那么另一个单位应做其他事情。
第一种测试是通过标准断言完成的(在OCHamcrest的情况下assertThat()
调用)。第二种测试(正确地)通过验证测试双精度(在OCMockito的情况下verify()
调用)完成。
模拟被测系统没有任何意义。如果您发现有必要测试内部行为(即被测系统调用的特定方法),那么您需要将这些行为映射到状态。在您的情况下,这意味着ClassA实现了一个标志,例如 BOOL nameValidated (最好使用getter isNameValidated )或变量,例如 NSString * validatedName