使用 OCMockito 验证方法调用

Posted

技术标签:

【中文标题】使用 OCMockito 验证方法调用【英文标题】:Verify method call with OCMockito 【发布时间】:2013-03-28 19:34:53 【问题描述】:

我在 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 是否被执行。

【问题讨论】:

【参考方案1】:

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

内部状态测试如下:

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

外部行为测试如下:

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

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

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

【讨论】:

以上是关于使用 OCMockito 验证方法调用的主要内容,如果未能解决你的问题,请参考以下文章

使用 OCMockito 模拟无效的方法

OCMockito / OCHamcrest 验证数组包含对象属性

使用 OCMockito 测试发送到模拟协议的参数

如何使用 mockito verify() 调用两次方法来验证方法

如何验证使用 XCTAssert 调用了类方法?

使用 Mockito 未调用 Object 参数的验证方法