Stubbing methods that return values

In this recipe, we will stub a method that returns a value so that it returns our desired result.

Getting ready

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;
    }
}

How to do it...

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:

  1. For the BDD approach, call BDDMockito.willReturn(value).given(spy).methodToStub(). Or, in the standard manner, call Mockito.doReturn(value).when(spy).methodToStub().
  2. Whichever approach you've chosen, you have to provide the desired output in the willReturn(...) or thenReturn(...) method, and pass the spy itself in the given(...) or when(...) method.
  3. Remember that the last passed value during stubbing will be returned for each stubbed method call. Have a look at the following code:
    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).

Note

You have to bear in mind that if you try to stub a method with the BDDMockito.given(...).willReturn(...) call or in the standard manner—with the Mockito.when(...).thenReturn(...) call—then you will actually call the spy's method that you want to stub!

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);
    }

}

How it works...

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.

There's more...

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()

See also

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.12.153.212