最近在写单元测试的时候遇到一个问题,把解决过程记录下来。
业务代码如下:
volume.getAttachments().get(0).getServerId()
其中getAttachments()
方法定义如下:
List<? extends VolumeAttachment> getAttachments();
VolumeAttachment
定义如下:
package org.openstack4j.model.storage.block;
import org.openstack4j.model.ModelEntity;
public interface VolumeAttachment extends ModelEntity {
String getDevice();
String getHostname();
String getId();
String getServerId();
String getVolumeId();
}
其有一个实现类CinderVolumeAttachment
。
如果按照正常操作写出下面的语句:
CinderVolumeAttachment cinderVolumeAttachment = Mockito.mock(CinderVolumeAttachment.class);
List<CinderVolumeAttachment> testList = new ArrayList<>(1);
testList.add(cinderVolumeAttachment);
Mockito.when(volume.getAttachments()).thenReturn(testList);
Mockito.doReturn(cinderVolumeAttachment).when(volume).getAttachments().get(Mockito.anyInt())
不好意思,编译失败,错误提示:Cannot resolve method 'thenReturn(java.util.List<org.openstack4j.openstack.storage.block.domain.CinderVolumeAttachment>)'
。
改成以下写法:
Mockito.doReturn(testList).when(volume).getAttachments();
Mockito.doReturn(cinderVolumeAttachment).when(volume).getAttachments().get(Mockito.anyInt());
编译正常,但是运行时出错,错误提示如下:
org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
CinderVolumeAttachment$MockitoMock$175542215 cannot be returned by getAttachments()
getAttachments() should return List
***
If you're unsure why you're getting above error read on.
Due to the nature of the syntax above problem might occur because:
1. This exception *might* occur in wrongly written multi-threaded tests.
Please refer to Mockito FAQ on limitations of concurrency testing.
2. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies -
- with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method.
坑爹的地方来了,怎么解决这个问题呢,很简单,不要mock get(0)
这个操作。代码删掉一行,改成下面这样就可以了:
CinderVolumeAttachment cinderVolumeAttachment = Mockito.mock(CinderVolumeAttachment.class);
Mockito.when(cinderVolumeAttachment.getServerId()).thenReturn("123");
List<CinderVolumeAttachment> testList = new ArrayList<>(1);
testList.add(cinderVolumeAttachment);
Mockito.doReturn(testList).when(volume).getAttachments();
具体原因不明,list.get()
是有什么诅咒不能mock吗?