In this recipe, we will stub a method that returns a value so that it returns our desired result.
For this recipe, our system under test will be MeanTaxFactorCalculator
, which calls TaxFactorFetcher
twice to get a tax factor for the given person and then calculates a mean value for those two results as follows:
public class MeanTaxFactorCalculator { private final TaxFactorFetcher taxFactorFetcher; public MeanTaxFactorCalculator(TaxFactorFetcher taxFactorFetcher) { this.taxFactorFetcher = taxFactorFetcher; } public double calculateMeanTaxFactorFor(Person person) { double taxFactor = taxFactorFetcher.getTaxFactorFor(person); double anotherTaxFactor = taxFactorFetcher.getTaxFactorFor(person); return (taxFactor + anotherTaxFactor) / 2; } }
To stub nonvoid methods so they return a given value, you have to perform the following steps:
BDDMockito.given(mock.methodToStub()).willReturn(value),
or in the standard way, call Mockito.when(mock.methodToStub()).thenReturn(value)
.given(...)
or when(...)
methods, you have to provide the mock's method call, and in the willReturn(...)
or thenReturn(...)
methods, you have to provide the desired output.given(taxFetcher.getTax()).willReturn(50, 100);
Then, regardless of the number of taxFetcher.getTax()
method executions, you will first return 50
and then, you will always receive 100
(until it's stubbed again).
Let's check the JUnit test. Refer to Chapter 1, Getting Started with Mockito, for the TestNG configuration (remember that I'm using BDDMockito.given(...)
and AssertJ's BDDAssertions.then(...)
static methods. Check out Chapter 7, Verifying Behavior with Object Matchers, for more details on how to work with AssertJ or how to do the same with Hamcrest's assertThat(...)
):
@RunWith(MockitoJUnitRunner.class) public class MeanTaxFactorCalculatorTest { @Mock TaxFactorFetcher taxFactorFetcher; @InjectMocks MeanTaxFactorCalculator systemUnderTest; @Test public void should_calculate_mean_tax_factor() { // given double expectedTaxFactor = 10; given(taxFactorFetcher.getTaxFactorFor(any(Person.class))).willReturn(expectedTaxFactor); // when double meanTaxFactor = systemUnderTest.calculateMeanTaxFactorFor(new Person()); // then then(meanTaxFactor).isEqualTo(expectedTaxFactor); } }
What Mockito does internally when you stub methods is that it executes two main actions, validation and answer construction. When you call the given(...)
or when(...)
methods, the validation takes place for the following situations:
thenReturn(...)
or willReturn(...)
)As for the answer construction phase, it takes place on the execution of the willReturn(...)
or thenReturn(...)
method calls. Eventually, Mockito constructs the Returns
answer with the passed value and then delegates the execution to it.
Mockito allows for providing a series of possible stubbed results either by using the fluent interface API, or by means of varargs. The following snippet shows you how to stub a method and provide subsequent results by means of fluent API using JUnit (see Chapter 1, Getting Started with Mockito, for the TestNG configuration):
@RunWith(MockitoJUnitRunner.class) public class MeanTaxFactorCalculatorTest { @Mock TaxFactorFetcher taxFactorFetcher; @InjectMocks MeanTaxFactorCalculator systemUnderTest; @Test public void should_calculate_mean_tax_factor_for_two_different_tax_factors() { // given double taxFactor = 10; double anotherTaxFactor = 20; double expectedMeanTaxFactor = (taxFactor + anotherTaxFactor) / 2; given(taxFactorFetcher.getTaxFactorFor(any(Person.class))).willReturn(taxFactor).willReturn(anotherTaxFactor); // when double meanTaxFactor = systemUnderTest.calculateMeanTaxFactorFor(new Person()); // then then(meanTaxFactor).isEqualTo(expectedMeanTaxFactor); } }
To achieve the same result using varargs, take the following code:
given(taxFactorFetcher.getTaxFactorFor(any(Person.class))).willReturn(taxFactor).willReturn(anotherTaxFactor);
Then, change it to the following code:
given(taxFactorFetcher.getTaxFactorFor(any(Person.class))).willReturn(taxFactor, anotherTaxFactor);
18.117.78.237