Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 494
user2968166 Avatar asked Aug 21 '26 15:08

user2968166


1 Answers

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

like image 162
Eugen Martynov Avatar answered Aug 23 '26 06:08

Eugen Martynov



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!