mockito从入门到通关( 二 )

InjectMocks使用@InjectMocks注解 , 可以将mock或spy的对象自动注入要测试的对象 。这在Spring等使用自动注入的框架里用得非常广泛 。
@MockMap<String, String> wordMap; @InjectMocksMyDictionary dic = new MyDictionary();// 类定义:class MyDictionary {    Map<String, String> wordMap;     public MyDictionary() {        wordMap = new HashMap<String, String>();    }    public void add(final String word, final String meaning) {        wordMap.put(word, meaning);    }    public String getMeaning(final String word) {        return wordMap.get(word);    }}打桩所谓打桩 , 其实就是mock的一个过程 。我们给定期望的输入和输入 , mock的对象就能够如我们期望的那样工作 。
打桩有两种写法 , 一种是传统的写法 , 一种是BDD **Behavior-Driven Development (行为驱动开发)**的写法 。
传统写法我们先看看传统的写法 , 传统的写法主要用Mockito类的方法 。基本是when-then-invoke-verify形式 。
when(phoneBookRepository.contains(momContactName))  .thenReturn(false); phoneBookService.register(momContactName, momPhoneNumber); verify(phoneBookRepository)  .insert(momContactName, momPhoneNumber);BDD写法BDD写法主要是用BDDMockito类的方法 , 看起来是given–will-invoke-then的形式 。
given(phoneBookRepository.contains(momContactName))  .willReturn(false); phoneBookService.register(momContactName, momPhoneNumber); then(phoneBookRepository)  .should()  .insert(momContactName, momPhoneNumber);动态mock有时候我们可能会遇到这个问题:在方法内部可能有循环或者递归 , 会多次调用其它对象的方法 , 但输入的参数不同 , 我们在mock的时候 , 期望它根据不同的输入参数返回不同的结果 。这个时候如果一个一个写given , 就需要写很多次 。但其实可以用动态mock来做 。它是基于InvocationOnMock来实现的 。
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的不足Mockito可以说是Java语言最流行的mock框架了 。但它不是所有对象都可以mock的 , 有一些限制 。
Mockito在3.4.0以前 , 是不能mock静态方法的 。这取决于它的底层实现 , 是使用动态代理来做的 。而动态代理是代理静态方法、final方法和private方法的 。
一般来说 , 我们不应该mock静态方法、final方法和private方法的 。但有时候可能会有这样的需求 , 比如Apache和guava框架 , 就使用了大量的静态方法提供一些工具类 。如果需要Mock的话 , 就得配合PowerMock等框架来实现 。但PowerMock框架目前还不支持JUnit 5 。
在Mockito 3.4.0 , 开始支持mock静态方法 , 底层是通过修改字节码来实现的 。但性能很差 , mock一个实例大概要一秒多 , 大家酌情使用 。
关于作者我是Yasin , 一个有颜有料又有趣的程序员 。
微信公众号:编了个程
个人网站:https://yasinshaw.com




推荐阅读