Mocking a List and attempting to iterate over it

后端 未结 3 950
一生所求
一生所求 2021-01-21 02:25

Currently using Mockito to Test a method from one of my classes. My class contains a List, and the method takes in an object of the same class. The issue is when I attempt to it

3条回答
  •  南方客
    南方客 (楼主)
    2021-01-21 02:49

    There are some fundamental issues why your example not does work and throws a NullPointerException.

    1. The call to add() on the mocked list effectively doesn't do anything. All void methods on mocks are "no-ops" by default
    2. Iterating over a list using for-each syntax calls Collection.iterator() under the hood. This returns null, because you've not setup mockito to return anything else.

    Instead, I would not mock the list and instead pass an actual list. Arrays.asList() is convenient for testing.

    @Before
    public void setUp(){
        MockitoAnnotations.initMocks(this);
        shipment = new Shipment(1, Arrays.asList(mockOrder1, mockOrder2));
        shipment2 = new Shipment(2, Arrays.asList(mockOrder3));
    }
    

    If you're determined to mock a list then you'll have to mock its behaviour, i.e. making the add() actually store something and .iterator() return an iterator. This can be done rather painfully as follows. I've only included this to demonstrate the principle.

    @Mock
    private List mockedList;
    
    @Before
    public void init() {
        MockitoAnnotations.initMocks(this);
    
        List realList = new ArrayList<>();
        doAnswer(new Answer() {
            @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>() {
    
            @Override
            public Iterator 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);
        }
    }
    

提交回复
热议问题