17

I came across a problem and I can't find an elegant solution.

So the problem is with a mock of Selenium web driver, and I dont know how should I test/mock void methods.

public void clickAndWait(String locator) {
    if(isElementPresent(locator) == false) throw some exception;
    selenium.clickAndWait(); //a problematic delegating call to selenium
}

So what I am asking is, how to properly test such a method, one test would be for exception being thrown, but how properly make test of that void method I delegate to?

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Jarek
  • 7,425
  • 15
  • 62
  • 89
  • 5
    Just out of curiosity, why do you write unit tests for an integration test? – Luciano Fiandesio Jun 17 '11 at 08:13
  • Possible duplicate of [How to make mock to void methods with mockito](https://stackoverflow.com/questions/2276271/how-to-make-mock-to-void-methods-with-mockito) – centic Sep 26 '17 at 09:17

6 Answers6

30

The following code sample from this Mockito documentation illustrates how to mock a void method:

doThrow(new RuntimeException()).when(mockedList).clear();

// following throws RuntimeException:
mockedList.clear();
hoipolloi
  • 7,984
  • 2
  • 27
  • 28
22
doAnswer(new Answer<Void>() {
        @Override
        public Void answer(InvocationOnMock invocation) throws Throwable {

            return null;
        }
    }).when(mock).method((SomeClass) anyObject());
Marcin Michalski
  • 1,266
  • 13
  • 17
  • 1
    +1 Useful answer showing how to use doThrow/doAnswer/etc when the method takes parameters i.e. The casting with `anyObject()`. – David Spence Mar 18 '14 at 11:15
  • Hi Marcin, I tried giving the same and getting error mentioned in http://stackoverflow.com/questions/27142314/powermock-mocking-void-method-throws-error Can you kindly have a look at that? – sriram Dec 01 '14 at 21:20
10

The previous answers have been stressing on doing something (throwing an exception possibly) at every call. This way when you do something like :

doThrow(new RuntimeException()).when(mockedList).clear();

and then call the stubbed service (or logic) like :

mockedList.clear();

it will generate an exception. What if you want to test for a proper functioning of method maybe writing positive test case. Mocking a void returning method for such case could be done by :

doNothing().when(mockedList).clear();

which means that since you stubbed the clear() method for mockedList mock, you can be sure that this method is not going to effect the logic of the unit and still you can check the rest of the flow without generating an exception.

Sourabh
  • 1,253
  • 6
  • 21
  • 39
  • Hi Sourabh, I tried the same solution and getting the exception as mentioned in http://stackoverflow.com/questions/27142314/powermock-mocking-void-method-throws-error Can you kindly have a look at that? – sriram Dec 01 '14 at 21:22
1

You can also use:

  • The method Mockito.verify(mock/spy) to check how many times the method has been called.
  • Or use the argument captor to see/check some parameters passed to the void method.
jakcam
  • 1,789
  • 2
  • 12
  • 14
0

You can trow an exception on your method call, here is a small example how to do it:

doThrow(new RuntimeException()).when(mockedList).clear();

then you call mockedList.clear(); mocked method will throw an exception.

Or you can count how many times your method was called, here is a small example how to do it:

verify(mockedList, times(1)).clear(); 
Mindaugas Jaraminas
  • 3,261
  • 2
  • 24
  • 37
0

In Java 8 this can be made a little cleaner

doAnswer((i) -> {
  // Do stuff with i.getArguments() here
  return null;
}).when(*mock*).*method*(*methodArguments*);

The return null; is important and without it the compile will fail with some fairly obscure errors as it won't be able to find a suitable override for doAnswer.

Tim B
  • 40,716
  • 16
  • 83
  • 128