jeudi 23 juin 2016

Random Mockito Stubbing exception

I have the following code snippet from a unit test using Mockito which has happily been passing for months/years.

    @Test
    public void testAddRemoveTarFile() throws IOException, GeneralSecurityException {
    //add a TAR file
    TableRowCount downloadRowCount = new TableRowCount(tableDownloads);

    //create the item that will appear in the table row 
    MyHSAItem item = createMyHSAItem();
    Mockito.when(model.getConfigurations(Type.TAR)).thenReturn(Arrays.asList(item));

    //get the table model
    JTable downloadsTable = (JTable)UI.findComponent(getPanel(), "download");
    final MyHSATableModel tableModel = (MyHSATableModel ) downloadsTable.getModel();

    final MyHSAEvent event = Mockito.mock(MyHSAEvent.class);
    Mockito.when(event.getType()).thenReturn(MyHSAEvent.Type.MODEL);

    //Fire table event when adding observation
    final File xmlFile = Mockito.mock(File.class);
    Mockito.doAnswer(new Answer<Void>() {
        @Override
        public Void answer(InvocationOnMock invocation) throws Throwable {
            tableModel.modelChanged(event);
            return null;
        }
    }).when(model).addObservation(xmlFile);

    //Fire table event when deleting observation
    Mockito.doAnswer(new Answer<Void>() {
        @Override
        public Void answer(InvocationOnMock invocation) throws Throwable {
            tableModel.modelChanged(event);
            return null;
        }
    }).when(model).delete(item, true);

    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            UI.findButtonWithText(getPanel(), "Add ...").doClick();
        }
    });

    //select a file, table row should update
    chooseFile(xmlFile);
    ensureEquals(1, downloadRowCount, TIMEOUT);

    // Remove download + cancel
    UI.leftClick(tableDownloads);
    clickRemove("Cancel");
    ensureEquals(1, downloadRowCount, TIMEOUT);

    // Remove download + OK
    UI.leftClick(tableDownloads);
    Mockito.when(model.getConfigurations(Type.TAR)).thenReturn(new ArrayList<MyHSAItem>());
    clickRemove("OK");
    ensureEquals(0, downloadRowCount, TIMEOUT);
}

Suddenly it failed just once with:

org.mockito.exceptions.misusing.UnfinishedStubbingException:
Unfinished stubbing detected here:
-> at herschel.ia.pal.pool.hsa.gui.MyHsaPreferencePanelTest.testAddRemoveTarFile(MyHsaPreferencePanelTest.java:257)

E.g. thenReturn() may be missing.
Examples of correct stubbing:
when(mock.isOk()).thenReturn(true);
when(mock.isOk()).thenThrow(exception);
doThrow(exception).when(mock).someVoidMethod();
Hints:
1. missing thenReturn()
2. although stubbed methods may return mocks, you cannot inline mock creation (mock()) call inside a thenReturn method (see issue 53)

I understand this error but not how it can randomly happen. The Mockito.doAnswer seems to be the problem. I am not inlining mocks and it seems to be ok and has always worked. What can it be?

Thanks for any help

Aucun commentaire:

Enregistrer un commentaire