简体   繁体   中英

Mockito stubbing void methods

I am currently writing unit tests for my selenium project and I am using Mockito to mock up my webelements and drivers.

The problem I am having is that I have a function that is used to change the radio option in a list of radio buttons but I am having a problem with this. the code looks like this:

@Test
public void testChangeRadioState(){
    WebElement mockElement           = mock(WebElement.class);
    List<WebElement> mockElementList = new ArrayList<>();
    WebElement selectedMockElement   = mock(WebElement.class);


    /*The when statements*/
    when(selectedMockElement.isSelected()).thenReturn(true);
    doReturn(when(mockElement.isSelected()).thenReturn(true)).when(mockElement).click();
    doReturn(when(selectedMockElement.isSelected()).thenReturn(false)).when(mockElement).click();

   /*Add a selected and a none selected element to the list*/
    mockElementList.add(mockElement);
    mockElementList.add(selectedMockElement);

    /*The method that is beeing tested*/
    elementSetter.changeRadioState(mockElementList);

    Assert.assertTrue("The radio state was not selected",mockElement.isSelected());
}

What I am trying to do int he doReturn part is to tell the element "mockElement" that when it recieves a click it should allways return true on a isSelected() call. but since Click() is a void function it won't let me do that. Anybody know a way around this?

Ok, it is separate topic - what you are testing and would I mock things so deep.

I would just rewrite test like this:

@Test
public void testChangeRadioState() {
    WebElement mockElement           = mock(WebElement.class);
    WebElement selectedMockElement   = mock(WebElement.class);
    List<WebElement> mockElementList = new ArrayList<>();

    /*The when statements*/
    when(selectedMockElement.isSelected()).thenReturn(true);
    // By default mockito will return false but maybe I want to highlight 
    // that this is important
    when(mockElement.isSelected()).thenReturn(false);

    /*Add a selected and a none selected element to the list*/
    mockElementList.add(mockElement);
    mockElementList.add(selectedMockElement);

    /*The method that is beeing tested*/
    elementSetter.changeRadioState(mockElementList);

    verify(selectedMockElement).click();
    // according to test method name I would add 
    // one more verification that something was dis-selected
}

Another variant with state which I think has unnecessary mocks:

boolean selected;
@Test
public void testChangeRadioState() {
    selected = false;
    WebElement mockElement           = mock(WebElement.class);
    WebElement selectedMockElement   = mock(WebElement.class);
    List<WebElement> mockElementList = new ArrayList<>();

    /*The when statements*/
    when(selectedMockElement.isSelected()).thenReturn(true);
    doAnswer(new Answer<Object>() {
        public Object answer(InvocationOnMock invocation) {
            selected = true;
            return null;
        }
    }).when(mockElement).click();
    /*Add a selected and a none selected element to the list*/
    mockElementList.add(mockElement);
    mockElementList.add(selectedMockElement);

    /*The method that is beeing tested*/
    elementSetter.changeRadioState(mockElementList);

    Assert.assertTrue("The radio state was not selected", selected);
    // according to test method name I would add 
    // one more verification that something was dis-selected
}

But again there is misleading in names. For example I would expect that there are elements which don't become selected when they clicked . Question again about what you are testing

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM