当前正在使用Mockito从我的一个类中测试一种方法.我的班级包含一个List,并且该方法接受同一班级的对象.问题是当我尝试从对象遍历List时.我得到一个指向列表的空指针.在下面,您将看到代码片段.
private Shipment shipment;
private Shipment shipment2;
@Mock
private Order mockOrder1;
@Mock
private Order mockOrder2;
@Mock
private Order mockOrder3;
@Mock
private ArrayList<Order> mockShipmentOrders;
@Mock
private ArrayList<Order> mockShipmentOrders2;
@Before
public void setUp(){
MockitoAnnotations.initMocks(this);
mockShipmentOrders.add(mockOrder1);
mockShipmentOrders.add(mockOrder2);
mockShipmentOrders2.add(mockOrder3);
shipment = new Shipment(1, mockShipmentOrders);
shipment2 = new Shipment(2, mockShipmentOrders2);
}
@Test
public void test_mergeShipments_increasesByOneWhenAShipmentOfOneAddedToAShipmentORderSizeOfTwo(){
shipment.mergeShipments(shipment2);
assertEquals(3, shipment.getShipmentOrders().size());
}
上面可以看到我的模拟测试,下面是我的Class和方法:
公共类货运{
private long shipmentID;
private List<Order> shipmentOrders;
public Shipment(long shipmentID, List<Order> shipmentOrders){
this.shipmentID = shipmentID;
this.shipmentOrders = shipmentOrders;
}
public List<Order> getShipmentOrders(){
return shipmentOrders;
}
public void mergeShipments(Shipment shipment2){
List<Order> existingShipment = shipment2.getShipmentOrders();
for (Order order : existingShipment){
shipmentOrders.add(order);
}
}
当我运行测试时,我得到了以下行的java.lang.NullPointerException:for(Order order:existingShipment){
在mergeShipemts();中
问题是;是否可以模拟列表,调用该列表,然后在该模拟列表上运行foreach?
解决方法:
为什么您的示例无法正常工作并引发NullPointerException有一些基本问题.
>对模拟列表上的add()的调用实际上没有任何作用.默认情况下,模拟中的所有void方法均为“ no-ops”
>使用for-each语法遍历列表,在后台调用Collection.iterator().这将返回null,因为您尚未将Mockito设置为返回其他任何内容.
相反,我不会模拟该列表,而是传递实际列表. Arrays.asList()便于测试.
@Before
public void setUp(){
MockitoAnnotations.initMocks(this);
shipment = new Shipment(1, Arrays.asList(mockOrder1, mockOrder2));
shipment2 = new Shipment(2, Arrays.asList(mockOrder3));
}
如果确定要模拟列表,则必须模拟其行为,即使add()实际上存储一些东西,而.iterator()返回迭代器.如下所述,这可能非常痛苦.我仅包括此内容以说明原理.
@Mock
private List<String> mockedList;
@Before
public void init() {
MockitoAnnotations.initMocks(this);
List<String> realList = new ArrayList<>();
doAnswer(new Answer<String>() {
@Override
public String answer(InvocationOnMock invocation) throws Throwable {
realList.add(invocation.getArgumentAt(0, String.class));
return null;
}
}).when(mockedList).add(any());
when(mockedList.iterator()).thenAnswer(new Answer<Iterator<String>>() {
@Override
public Iterator<String> answer(InvocationOnMock invocation) throws Throwable {
return realList.iterator();
}
});
mockedList.add("bar");
mockedList.add("baz");
}
@Test
public void iterateOverMockedList() {
for (String each : mockedList) {
System.out.println(each);
}
}