2

我在 ClassA 中有这两种方法

-(IBAction)onSubmit;
-(void)validateName:(NSString*)name;

@执行

- (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 是否已执行。

4

1 回答 1

5

适当的单元测试测试内部状态和外部行为。你的单元测试是测试你的代码是否做某事,而不是它是如何做某事的。状态验证告诉您达到了预期的结果,而行为验证告诉您协作对象正确地与被测系统交互。这使您可以做一些很棒的事情,例如重构。

内部状态测试如下:

给定一个初始状态,如果被测系统做了某事,那么 结果状态应该是这个

外部行为测试如下:

如果被测系统做某事,那么另一个单元应该做其他事情

第一种测试是通过标准断言(assertThat()在 OCHamcrest 的情况下调用)完成的。第二种测试(正确)通过验证测试替身(verify()在 OCMockito 的情况下调用)来完成。

模拟被测系统没有任何意义。如果您发现有必要测试内部行为(即被测系统调用的特定方法),那么您需要将这些行为映射到状态。在您的情况下,这意味着 ClassA 实现了一个标志,例如BOOL nameValidated(最好使用 getter isNameValidated)或一个变量,例如NSString *validatedName

于 2013-04-06T13:35:59.223 回答