6

以前的项目中,后端项目的单元测试都是构造出相应的数据然后存入数据库中,这种方式,在功能简单时还好,当功能趋于复杂时,就需要花费大量的时间去构造实验数据,前段时间,潘老师找到了一种新的单元测试方式——使用Mockito 。前两天作出了第一次尝试,期间遇到了一些问题,在询问潘老师后得到了解决,在此记录一番。

如何使用

使用方法可以看这篇文章

Invalid use of argument matchers!

开始时使用的

Mockito.when(scoreServiceSpy.  
       getAllFailScoreByPage(Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.any(Pageable.class))).thenReturn(mockScorePage);

使用的时候,会出现如下错误。
image.png
解决办法在错误中也已经给出,当使用matchers,所有的参数都需要提供为matcher
image.png
但是我上面的方法中确实所有的都是用的matcher呀,继续看潘老师的教程,
image.png
尝试切换成

doReturn().when()

不过在这里又犯了一个粗心的错误……

// 我写的代码
Mockito.doReturn(mockScorePage).when(scoreServiceSpy
        .getAllFailScoreByPage(Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.any(Pageable.class)));

// 正确的代码  
Mockito.doReturn(mockScorePage).when(scoreServiceSpy)  
        .getAllFailScoreByPage(Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.any(Pageable.class));

括号的位置错了!

开始时,发现这个也错,以为问题不在这,而是写法有问题,翻来覆去找都没找到问题,只能求助于潘老师了。

经过潘老师的讲解,总算明白了。

首先,我们需要明白两种写法的区别

doReturn().when()与when().thenReturn()

潘老师在教程中已经提供了延伸阅读,只是当时还没来得及看。

官方的说法

doReturn().when()是无副作用的。
when().thenReturn()是有副作用的

上述说法可以这么理解:

使用Mockito.when(scoreServiceSpy.getAllFailScoreByPage(xxx)),
scoreServiceSpy.getAllFailScoreByPage(xxx)这个方法就会真正的被执行。
而使用Mockito.doReturn(mockScorePage).when(scoreServiceSpy).getAllFailScoreByPage(xxxx)时,后面的方法并不会执行。

到这也大概明白了上面出现问题的原因。
进入getAllFails()里面。
image.png
可以看到findAll()有两个参数,其中pageable是通过matcher生成的,specification不是。

Unfinished stubbing detected here:

问题还没有完全解决。
image.png

出现这个的原因,潘老师猜测是因为第三条,因为在单元测试中使用了@MockBean,通过这个注入的对象有几个特点:

  • 是全局的
  • 该对象有原对象的所有方法,但方法没有功能。
  • 调用有返回值的方法时,若没有通过Mockito设置返回值,就会出现上述错误。

所以,出现上述错误的原因可能是
image.png


笙歌会停
1k 声望45 粉丝

代码成就万世基积沙镇海 梦想永在凌云意意气风发