BDDMockito 快速指南,你学会了吗?

Mockito传统mock是在排列步骤中使用when(obj).then*()执行的,稍后,可以在A
首页 新闻资讯 行业资讯 BDDMockito 快速指南,你学会了吗?

概述

BDD一词最早由Dan North于2006年创造。BDD鼓励用自然的、可读的语言编写测试,重点关注应用程序的行为。

它定义了一种结构清晰的测试编写方式,分为三个部分(排列、动作、断言):

  • 给定一些先决条件(排列)

  • 行动发生时(行动)

  • 然后验证输出(Assert)

Maven依赖项:

<dependency><groupId>org.mockito</groupId><artifactId>mockito-core</artifactId><version>2.21.0</version></dependency>

包含以下静态导入,我们的测试可以变得更可读:

importstatic org.mockito.BDDMockito.*;

BDDMockito扩展了Mockito,所以我们不会错过传统Mockito API提供的任何功能。

Mockito与BDDMockito

Mockito传统mock是在排列步骤中使用when(obj).then*()执行的,稍后,可以在Assert步骤中使用verify()验证与mock的交互。

BDDMockito为各种Mockito方法提供了BDD别名,因此我们可以使用given(而不是when)编写Arrange步骤,同样,我们可以使用then(而不是verify)编写Assert步骤。

让我们看一个使用传统Mockito的测试体示例:

when(phoneBookRepository.contains(momContactName)).thenReturn(false);phoneBookService.register(momContactName,momPhoneNumber);verify(phoneBookRepository).insert(momContactName,momPhoneNumber);

让我们看看与BDDMockito相比如何:

given(phoneBookRepository.contains(momContactName)).willReturn(false);phoneBookService.register(momContactName,momPhoneNumber);then(phoneBookRepository).should().insert(momContactName,momPhoneNumber);

BDDMockito Mock

让我们试着测试PhoneBookService,我们需要模拟PhoneBookRepository:

publicclass PhoneBookService {
    private PhoneBookRepository phoneBookRepository;publicvoid register(String name,String phone){if(!name.isEmpty()&&!phone.isEmpty()&&!phoneBookRepository.contains(name)){
            phoneBookRepository.insert(name,phone);}
    }publicString search(String name){if(!name.isEmpty()&&phoneBookRepository.contains(name)){returnphoneBookRepository.getPhoneNumberByContactName(name);}returnnull;}
}

BDDMockito作为Mockito允许我们返回一个可能是固定的或动态的值。它还允许我们抛出一个异常:

  • 返回固定值

使用BDDMockito,我们可以很容易地将Mockito配置为在调用mock对象目标方法时返回固定结果:

given(phoneBookRepository.contains(momContactName)).willReturn(false);phoneBookService.register(xContactName,"");then(phoneBookRepository).should(never()).insert(momContactName,momPhoneNumber);
  • 返回动态值

BDDMockito允许我们提供一种更复杂的返回值的方法。我们可以根据输入返回一个动态结果:

given(phoneBookRepository.contains(momContactName)).willReturn(true);given(phoneBookRepository.getPhoneNumberByContactName(momContactName)).will((InvocationOnMock invocation)->invocation.getArgument(0).equals(momContactName)? momPhoneNumber 
      :null);phoneBookService.search(momContactName);then(phoneBookRepository).should().getPhoneNumberByContactName(momContactName);
  • 引发异常

告诉Mockito抛出异常非常简单:

given(phoneBookRepository.contains(xContactName)).willReturn(false);willThrow(new RuntimeException()).given(phoneBookRepository).insert(any(String.class),eq(tooLongPhoneNumber));try {
    phoneBookService.register(xContactName,tooLongPhoneNumber);fail("Should throw exception");} catch(RuntimeException ex){ }then(phoneBookRepository).should(never()).insert(momContactName,tooLongPhoneNumber);

注意我们是如何交换given和will的位置,这是强制性的,以防我们mock一个没有返回值的方法。

还要注意,我们使用了(any,eq)等参数匹配器,以提供一种更通用的基于标准而非固定值的mock方式。

结论

我们讨论了BDDMockito如何试图将BDD特性引入Mockito测试,并讨论了Mockito和BDDMockito之间的一些差异。

38    2023-07-30 22:29:51    BDDMockito Assert 测试