In this recipe, we will stub a void method. A void method is one that doesn't return a value. Remember that since we want to partially stub a mock, it most likely means that our class is doing too much, and that is quite true for this scenario. It is best practice to not write such code – always try to follow the SOLID principles.
For this recipe, our system under test will be the PersonDataUpdator
class, which delegates most of the work to its collaborator, TaxFactorService
. The latter calculates the mean value of the tax factor (for simplicity, it's a fixed value) and then updates the person's tax data via a web service (since it's a simple example, we do not have any real web service calls):
public class PersonDataUpdator { private final TaxFactorService taxFactorService; public PersonDataUpdator(TaxFactorService taxFactorService) { this.taxFactorService = taxFactorService; } public boolean processTaxDataFor(Person person) { try { double meanTaxFactor = taxFactorService.calculateMeanTaxFactor(); taxFactorService.updateMeanTaxFactor(person, meanTaxFactor); return true; } catch (ConnectException exception) { System.err.printf("Exception occurred while trying update person data [%s]%n", exception); throw new TaxFactorConnectionException(exception); } } }
The TaxFactorService
class is shown in the following code (note that updateMeanTaxFactor
is throwing a checked exception, ConnectException
):
public class TaxFactorService { private static final double MEAN_TAX_FACTOR = 0.5; public void updateMeanTaxFactor(Person person, double meanTaxFactor) throws ConnectException { System.out.printf("Updating mean tax factor [%s] for person with defined country%n", meanTaxFactor); } public double calculateMeanTaxFactor() { return MEAN_TAX_FACTOR; } }
To stub a spy's void method in such a way that it does nothing, you have to perform the following steps:
BDDMockito.willDoNothing().given(spy).methodToStub()
. Or, in the standard manner, call Mockito.doNothing().when(spy).methodToStub()
.willDoNothing()
or doNothing()
, you will pass the spy itself in the given(...)
or when(...)
method.willDoNothing().willThrow(exception).given(taxFetcher).getTax();
As shown in the preceding code, regardless of the number of taxFetcher.getTax()
method executions, the method will first do nothing and then always throw an exception (until stubbed again).
The following snippet depicts the aforementioned scenario for JUnit. See Chapter 1, Getting Started with Mockito, for the TestNG configuration (I'm using the BDDMockito.given(...)
and AssertJ's BDDAssertions.then(...)
static methods. Check out Chapter 7, Verifying Behavior with Object Matchers, on how to work with AssertJ or how to do the same with Hamcrest's assertThat(...)
). Have a look at the following snippet:
@RunWith(MockitoJUnitRunner.class) public class PersonDataUpdatorTest { @Spy TaxFactorService taxFactorService; @InjectMocks PersonDataUpdator systemUnderTest; @Test public void should_successfully_update_tax_factor_for_person() throws ConnectException { // given willDoNothing().given(taxFactorService).updateMeanTaxFactor(any(Person.class), anyDouble()); // when boolean success = systemUnderTest.processTaxDataFor(new Person()); // then then(success).isTrue(); } }
A spy is a special case of a mock. Refer to the Stubbing void methods recipe of Chapter 4, Stubbing Behavior of Mocks, for more information.
Say you want to make a method first throw an exception and do that only once; after that, you want the method to do nothing. Take a look at the following snippet, which shows how to achieve this:
willThrow(exception).willNothing().given(spy).methodToSpy();
doReturn()
|doThrow()
|doAnswer()
|doNothing()
|doCallRealMethod()
family of methods at http://docs.mockito.googlecode.com/hg/1.9.5/org/mockito/Mockito.html#1218.191.234.150