Mockito void Method Example
In Mockito Hello World Example, we have learnt how to stub a non-void method that returns something. Sometimes we may also need to stub a void method which is what I am going to show in this article.
Before I start with my example, a bit about my setup:
- I am using Maven – the build tool
- Eclipse as the IDE, version Luna 4.4.1.
- TestNG is my testing framework, in case you are new to TestNG, please refer TestNG Maven Project Example.
- Add Mockito dependency to our
pom.xml
.
1. Mockito Void Method Example
The example I have chosen is about a dish that a customer is going to taste. Dish
object represents the dish. It has a void eat()
method which the customer object will call when served with the dish. If the dish is not the one customer is expecting then it will throw WrongDishException
.
In the next few sections, I will show you different ways of stubbing the void method eat()
to change its behavior.
The usual way to stub a non-void method is:
when(dish.eat()).thenReturn("some value");
But note that eat()
doesn’t return anything so naturally we won’t be able to use the above style of API.
We can stub a void method to throw an exception using doThrow()
. Other than that we can also make use of doNothing()
and doAnswer()
APIs.
Customer:
package com.javacodegeeks.mockito; public class Customer { public void eat(Dish dish) throws WrongDishException { try { System.out.println("Taste the food"); dish.eat(); System.out.println("Ate the food"); } catch (WrongDishException e) { System.out.println("Wrong dish!"); throw e; } catch (NotSuchATastyException e) { System.out.println("Not very tasty"); throw e; } } }
Dish:
package com.javacodegeeks.mockito; public interface Dish { void eat() throws WrongDishException; }
2. Stub void method Using deprecated API stubVoid
Originally, stubVoid()
was used for stubbing void methods with exceptions. For example, in test testEatUsingStubVoid()
, we stub eat()
to simply return without throwing an exception, we can do it using stubVoid()
and toReturn()
.
stubVoid(dish).toReturn().on().eat();
Now when we call customer.eat(dish)
, it doesn’t throw any exception.
But note that stubVoid()
is deprecated so we won’t use it any more. doThrow()
and doReturn()
replaces stubVoid()
because of improved readability and consistency with the family of doAnswer()
methods.
MockitoVoidExample:
package com.javacodegeeks.mockito; import static org.mockito.Mockito.*; import static org.testng.Assert.*; import org.mockito.InOrder; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; public class MockitoVoidExample { private Customer customer; private Dish dish; @BeforeMethod public void setupMock() { customer = new Customer(); dish = mock(Dish.class); } @Test public void testEatUsingStubVoid() throws WrongDishException { System.out.println("Train dish to not throw WrongDishException using stubVoid"); stubVoid(dish).toReturn().on().eat(); customer.eat(dish); System.out.println("Finished the dish, no exception thrown"); } }
Output:
Train dish to not throw WrongDishException using stubVoid Taste the food Ate the food Finished the dish, no exception thrown PASSED: testEatUsingStubVoid
3. Stub void method Using toReturn
In test testEatUsingDoNothing
, we replace stubVoid()
with doNothing()
and when()
.
doNothing().when(dish).eat();
MockitoVoidExample:
package com.javacodegeeks.mockito; import static org.mockito.Mockito.*; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; public class MockitoVoidExample { private Customer customer; private Dish dish; @BeforeMethod public void setupMock() { customer = new Customer(); dish = mock(Dish.class); } @Test public void testEatUsingStubVoid() throws WrongDishException { System.out.println("Train dish to not throw WrongDishException using stubVoid"); stubVoid(dish).toReturn().on().eat(); customer.eat(dish); System.out.println("Finished the dish, no exception thrown"); } @Test public void testEatUsingDoNothing() throws WrongDishException { System.out.println("Train dish to not throw WrongDishException using doNothing"); doNothing().when(dish).eat(); customer.eat(dish); System.out.println("Finished the dish, no exception thrown"); } }
Output:
Train dish to not throw WrongDishException using doNothing Taste the food Ate the food Finished the dish, no exception thrown PASSED: testEatUsingDoNothing
4. Stub void method Using doThrow
In evaluateFood()
, we stub method dish.eat()
to throw NotSoTastyException
using doThrow()
and when()
combination.
doThrow(NotSuchATastyException.class).when(dish).eat();
MockitoVoidExample:
package com.javacodegeeks.mockito; import static org.mockito.Mockito.*; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; public class MockitoVoidExample { private Customer customer; private Dish dish; @BeforeMethod public void setupMock() { customer = new Customer(); dish = mock(Dish.class); when(dish.getSpice()).thenReturn(null); } @Test public void testEatUsingStubVoid() throws WrongDishException { System.out.println("Train dish to not throw WrongDishException using stubVoid"); stubVoid(dish).toReturn().on().eat(); customer.eat(dish); System.out.println("Finished the dish, no exception thrown"); } @Test public void testEatUsingDoNothing() throws WrongDishException { System.out.println("Train dish to not throw WrongDishException using doNothing"); doNothing().when(dish).eat(); customer.eat(dish); System.out.println("Finished the dish, no exception thrown"); } @Test(expectedExceptions=NotSoTastyException.class) public void evaluateFood() throws WrongDishException { doThrow(NotSoTastyException.class).when(dish).eat(); customer.eat(dish); System.out.println("Won't reach here"); } }
Output:
Taste the food Not very tasty PASSED: evaluateFood
5. Stub void method Using doAnswer
Suppose we want to custom behavior a method’s behavior based on the arguments passed then we can use doAnswer()
API.
Answer
interface specifies an action that is executed when you interact with the mock’s method. We can customize the behavior based on the mock’s method name or the method arguments which is passed to it. In case of non-void methods, you can even make the answer
to customize the method’s return value.
In test ifSpiceThrowException()
, the customer orders for a spicy dish. If the dish is of medium spice then customer.eat(dish)
will return quietly. If the dish is too spicy then the overloaded eat(spice)
method is going to throw a RuntimeException
.
SpiceAnswer
implements Answer
and based on the degree of spice, it will either throw a RuntimeException
or return a value.
We stub the custom behavior using doAnswer()
and when()
APIs.
doAnswer(new SpiceAnswer()).when(dish).eat(spicy);
Dish:
package com.javacodegeeks.mockito; public interface Dish { void eat() throws WrongDishException; void eat(String spicy) throws WrongDishException; String getSpice(); }
MockitoVoidExample:
package com.javacodegeeks.mockito; import static org.mockito.Mockito.*; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; public class MockitoVoidExample { private Customer customer; private Dish dish; @BeforeMethod public void setupMock() { customer = new Customer(); dish = mock(Dish.class); when(dish.getSpice()).thenReturn(null); } @Test public void testEatUsingStubVoid() throws WrongDishException { System.out.println("Train dish to not throw WrongDishException using stubVoid"); stubVoid(dish).toReturn().on().eat(); customer.eat(dish); System.out.println("Finished the dish, no exception thrown"); } @Test public void testEatUsingDoNothing() throws WrongDishException { System.out.println("Train dish to not throw WrongDishException using doNothing"); doNothing().when(dish).eat(); customer.eat(dish); System.out.println("Finished the dish, no exception thrown"); } @Test(expectedExceptions=NotSoTastyException.class) public void evaluateFood() throws WrongDishException { doThrow(NotSoTastyException.class).when(dish).eat(); customer.eat(dish); System.out.println("Won't reach here"); } @Test(expectedExceptions=RuntimeException.class) public void ifSpiceThrowException() throws WrongDishException { System.out.println("Train dish to not throw NotSoTastyException when called first time and return in subsequent calls"); String spicy = "spicy"; when(dish.getSpice()).thenReturn(spicy); doAnswer(new SpiceAnswer()).when(dish).eat(spicy); customer.eat(dish); spicy = "too spicy"; when(dish.getSpice()).thenReturn(spicy); doAnswer(new SpiceAnswer()).when(dish).eat(spicy); customer.eat(dish); } private class SpiceAnswer implements Answer { @Override public String answer(InvocationOnMock invocation) throws Throwable { String arg = (String) invocation.getArguments()[0]; if ("too spicy".equals(arg)) { throw new RuntimeException("Spicy dish!"); } return arg; } } }
Output:
Train dish to not throw NotSoTastyException when called first time and return in subsequent calls Taste the food Ate the food Taste the food PASSED: ifSpiceThrowException
6. Stub void method with consecutive calls
Sometimes we may need to stub a method with different behaviors for each consecutive call of the same method.
In test eatMultipleDishes()
, NotSoTastyException
is thrown the first time customer.eat(dish)
is called. But no exception is thrown in the subsequent calls to customer.eat(dish)
.
doThrow(NotSoTastyException.class).doNothing().when(dish).eat();
MockitoVoidExample:
package com.javacodegeeks.mockito; import static org.mockito.Mockito.*; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.testng.Assert; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; public class MockitoVoidExample { private Customer customer; private Dish dish; @BeforeMethod public void setupMock() { customer = new Customer(); dish = mock(Dish.class); when(dish.getSpice()).thenReturn(null); } @Test public void testEatUsingStubVoid() throws WrongDishException { System.out.println("Train dish to not throw WrongDishException using stubVoid"); stubVoid(dish).toReturn().on().eat(); customer.eat(dish); System.out.println("Finished the dish, no exception thrown"); } @Test public void testEatUsingDoNothing() throws WrongDishException { System.out.println("Train dish to not throw WrongDishException using doNothing"); doNothing().when(dish).eat(); customer.eat(dish); System.out.println("Finished the dish, no exception thrown"); } @Test(expectedExceptions=NotSoTastyException.class) public void evaluateFood() throws WrongDishException { doThrow(NotSoTastyException.class).when(dish).eat(); customer.eat(dish); System.out.println("Won't reach here"); } @Test(expectedExceptions=RuntimeException.class) public void ifSpiceThrowException() throws WrongDishException { System.out.println("Train dish to not throw NotSuchATastyException when called first time and retun in subsquent calls"); String spicy = "spicy"; when(dish.getSpice()).thenReturn(spicy); doAnswer(new SpiceAnswer()).when(dish).eat(spicy); customer.eat(dish); spicy = "too spicy"; when(dish.getSpice()).thenReturn(spicy); doAnswer(new SpiceAnswer()).when(dish).eat(spicy); customer.eat(dish); } private class SpiceAnswer implements Answer { @Override public String answer(InvocationOnMock invocation) throws Throwable { String arg = (String) invocation.getArguments()[0]; if ("too spicy".equals(arg)) { throw new RuntimeException("Spicy dish!"); } return arg; } } @Test public void eatMultipleDishes() throws WrongDishException { System.out.println("Train dish to not throw NotSoTastyException when called first time and return in subsequent calls"); doThrow(NotSoTastyException.class).doNothing().when(dish).eat(); try { customer.eat(dish); Assert.fail("allows eating, should have failed with NotSoTastyException"); } catch(NotSoTastyException e) { System.out.println("Coudln't eat the dish, not very tasty"); } customer.eat(dish); System.out.println("Finished the dish, no exception thrown"); customer.eat(dish); System.out.println("Finished the dish, no exception thrown"); } }
Output:
Train dish to not throw NotSoTastyException when called first time and return in subsequent calls Taste the food Not very tasty Coudln't eat the dish, not very tasty Taste the food Ate the food Finished the dish, no exception thrown Taste the food Ate the food Finished the dish, no exception thrown PASSED: eatMultipleDishes
7. Download the Eclipse Project
This was an example of Mockito void Method.
You can download the full source code of this example here: mockitoVoid.zip