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

}

How to do it...

To stub nonvoid methods so they return a given value, you have to perform the following steps:

  1. For the BDD approach, call BDDMockito.given(mock.methodToStub()).willReturn(value), or in the standard way, call Mockito.when(mock.methodToStub()).thenReturn(value).
  2. Regardless of the chosen approach in the 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.
  3. Remember that the last passed value during the stubbing will be for each stubbed method call. In other words, say that you stub the mock as follows:
    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);
    }

}

How it works...

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:

  • Stubbing is not complete (when you forget to write thenReturn(...) or willReturn(...))
  • Argument matchers are misplaced (you can't use them outside of verification or stubbing)
  • Stubbing is performed on an object that is not a mock
  • Invalid checked exception is being thrown

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.

There's more...

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

See also

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

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