In this recipe, we will stub a method that returns a value so that it returns a custom answer of our choice.
For this recipe, our system under test will again 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; } }
Let's assume that depending on whether the person is from a defined or undefined country, the logic of calculating the factor by TaxFactorFetcher
is different.
To stub nonvoid methods so they execute the logic from the custom answer, you have to perform the following steps:
BDDMockito.given(mock.methodToStub()).willAnswer(answer)
, or in the standard way, call Mockito.when(mock.methodToStub()).thenAnswer(answer)
.given(...)
or when(...)
method, you have to provide the mock's method call, and in willAnswer(...)
or thenAnswer(...)
, you have to provide the desired Answer
implementation.given(taxFetcher.getTax()).willAnswer(new Answer1(), new Answer2());
Then, regardless of the number of taxFetcher.getTax()
method executions, first Answer1
will be executed, and then you will always have Answer2
executed (until it is stubbed again).
Now, let's move to the JUnit test. See 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, to learn 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_return_tax_factor_incremented_by_additional_factor_when_calculating_mean_tax_factor() { // given final double additionalTaxFactor = 100; final double factorForPersonFromUndefinedCountry = 200; given(taxFactorFetcher.getTaxFactorFor(any(Person.class))).willAnswer(new Answer<Object>() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { if (invocation.getArguments().length > 0) { Person person = (Person) invocation.getArguments()[0]; if (!person.isCountryDefined()) { return additionalTaxFactor + factorForPersonFromUndefinedCountry; } } return additionalTaxFactor; } }); // when double meanTaxFactor = systemUnderTest.calculateMeanTaxFactorFor(new Person()); // then then(meanTaxFactor).isEqualTo(additionalTaxFactor + factorForPersonFromUndefinedCountry); } }
Another thing to remember is that most likely, you won't have the need to create any special answers. If that is the case, it's highly probable that your scenario is getting too complicated. For additional information regarding Answers
, please refer to Chapter 2, Creating Mocks.
Please refer to the Stubbing methods that return values recipe for more information on the Mockito internals related to stubbing methods so that they throw exceptions.
It's worth mentioning that eventually, when the willThrow(...)
or thenThrow(...)
code is called, Mockito constructs the ThrowsException
answer with the passed exception and then delegates further execution to it.
Mockito provides a series of possible answers to be executed either by using the fluent interface API, or by means of varargs.
You can perform stubbing via a fluent API as follows:
given(...).willAnswer(answer1).willAnswer(answer2)...willAnswer(answer3)
Or, with the varargs style, you can perform the stubbing as follows:
given(...).willAnswer(answer1, answer2, …. answerN)
Please refer to the There's more... section of the Stubbing methods so that they throw exception recipe from this chapter for analogous test examples.
3.16.139.8