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 AverageTaxFactorCalculator
along with the TaxFactorFetcher
class. Together, they form a unit whose purpose is to calculate the average factor. The TaxFactorFetcher
class is called twice: once to get a tax factor from DB and once to get a tax factor for a given person. Then, it calculates an average out of those values. Have a look at the following code:
public class AverageTaxFactorCalculator { private final TaxFactorFetcher taxFactorFetcher; public AverageTaxFactorCalculator(TaxFactorFetcher taxFactorFetcher) { this.taxFactorFetcher = taxFactorFetcher; } public double calculateAvgTaxFactorFor(Person person) { double taxFactor = taxFactorFetcher.getTaxFactorFromDb(person); double anotherTaxFactor = taxFactorFetcher.getTaxFactorFor(person); return (taxFactor + anotherTaxFactor) / 2; } }
The implementation of the TaxFactorFetcher
looks as follows:
public class TaxFactorFetcher { static final double NO_COUNTRY_TAX_FACTOR = 0.3; static final double DEFAULT_TAX_FACTOR = 0.5; static final double DB_TAX_FACTOR = 0.8; public double getTaxFactorFor(Person person) { if (person.isCountryDefined()) { return DEFAULT_TAX_FACTOR; } return NO_COUNTRY_TAX_FACTOR; } public double getTaxFactorFromDb(Person person) { // simulation of DB access return DB_TAX_FACTOR; } }
We would like to test our system as a whole without calling the database, so we will have to only partially stub TaxFactorFetcher
. To do this, perform the following steps:
BDDMockito.willReturn(value).given(spy).methodToStub()
. Or, in the standard manner, call Mockito.doReturn(value).when(spy).methodToStub()
.willReturn(...)
or thenReturn(...)
method, and pass the spy itself in the given(...)
or when(...)
method.willReturn(50,100).given(taxFetcher).getTax();
As shown in the preceding line of code, regardless of the number of taxFetcher.getTax()
method executions, you will first return 50
and then always receive 100
(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, for more details 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 AverageTaxFactorCalculatorTest { @Spy TaxFactorFetcher taxFactorFetcher; @InjectMocks AverageTaxFactorCalculator systemUnderTest; @Test public void should_calculate_avg_tax_factor_for_person_without_a_country() { // given double storedTaxFactor = 10; double expectedAvgTaxFactor = 12; willReturn(storedTaxFactor).given(taxFactorFetcher).getTaxFactorFromDb(any(Person.class)); // when double avgTaxFactor = systemUnderTest.calculateAvgTaxFactorFor(new Person()); // then then(avgTaxFactor).isEqualTo(expectedAvgTaxFactor); } }
A spy is a special case of a mock. Refer to the Stubbing methods that return values recipe of Chapter 4, Stubbing Behavior of Mocks, for more information.
Mockito allows you to provide a series of possible stubbed results either by using the fluent interface API or by means of varargs.
If you need to pass a series of return values to the stubbed spy's method using the fluent API, you will have to stub the method invocation as follows:
willReturn(obj1).willReturn(obj2).given(spy).methodToStub()
Or, if you want to use varargs, you will have do it as follows:
willReturn(obj1, obj2).given(spy).methodToStub()
3.12.153.212