Using argument matchers for stubbing

Before going into detail regarding the different ways of stubbing method calls, we have to define the concept of argument matchers. When passing arguments to the mock's methods during the stubbing process, Mockito verifies argument values using the equals() method. In other words, when calling the following code:

Person smith = new Person();
given(taxFactorFetcher.getTaxFactorFor(smith).willReturn(10);

Mockito will check whether the person passed as an argument to the getTaxFactorFor(...) method equals to our person (in this case, Mr. Smith). If that is the case, only then will Mockito return 10 as the output of the getTaxFactorFor(...) method.

There are cases where you want to perform more complex verification of the passed argument. Mockito already gives you quite a few predefined argument matchers and also provides you with the integration with Hamcrest to create custom argument matchers (check Chapter 7, Verifying Behavior with Object Matchers, for more details on Hamcrest).

Note

In general, you should use equality or pass a matcher that starts with any prefix, which means you don't care about the passed value. If you are using more complex examples, then ensure your code isn't too complicated.

Getting ready

Let's take a look at the existing Mockito argument matchers that are present in the Matchers class:

  • Examples of argument matchers that start with the any prefix are any(), any(Person.class), anyDouble(), anyList(), and so on.
  • Examples of argument matchers that end with the That suffix are argThat(...), booleanThat(...), doubleThat(...), and so on. You can provide a custom Hamcrest matcher that matches the argument of the given type.
  • The startsWith(...) and endsWith(...) argument matchers are used for string comparison.
  • The eq(...) argument matcher checks for equality.
  • The isNotNull(), isNull(), and notNull() argument matchers provide verification against null values.
  • The refEq(...) argument matcher is used for reflection-equal verification (checks via reflection whether two objects are equal).

There is also the AdditionalMatchers class that contains some matchers, but it's better that you don't use it since it's only there to maintain compatibility with EasyMock.

Since using argument matchers is pretty straightforward, intuitive, and we have already been profiting from them throughout the book, we'll skip the business context of the test and move through a quick syntax example to a reminder regarding common mistakes while using argument matching.

How to do it...

To use Mockito's argument matchers, you have to ensure that when calling any method on a mock, you pass a matcher from the Matchers class instead of passing an argument.

Let's take a look at a couple of snippets that show us some of the possible matchers that Mockito has in the Matchers class in the example of a method that takes two parameters: an object of the Person type and a string:

/* match the method for any person and for the city of Warsaw */
given(irsDataFetcher.isIrsApplicable(any(Person.class), eq("Warsaw"))).willReturn(true);

/* match the method for any person and for the city starting with 'W' */
given(irsDataFetcher.isIrsApplicable(any(Person.class), startsWith("W"))).willReturn(true);

/* match the method for any Person and for the city ending with 'w' */
given(irsDataFetcher.isIrsApplicable(any(Person.class), endsWith("w"))).willReturn(true);

/* match the method for any person and for any city */
given(irsDataFetcher.isIrsApplicable(any(Person.class), anyString())).willReturn(true);

/* match the method for a person that equals another person and for any city */
given(irsDataFetcher.isIrsApplicable(refEq(new Person()), anyString())).willReturn(true);

/* match the method for the same reference of the person and for any city */
given(irsDataFetcher.isIrsApplicable(same(person), anyString())).willReturn(true);

/* match the method for a person called Lewandowski and for any city (using Hamcrest matcher) */
given(irsDataFetcher.isIrsApplicable(argThat(new ArgumentMatcher<Person>() {

            @Override
            public boolean matches(Object argument) {
                return "Lewandowski".equalsIgnoreCase(((Person)argument).getName());
            }

        }), anyString())).willReturn(true);

How it works...

All of the methods of the Matchers class return dummy values so that the code gets compiled. Internally, Mockito places a matcher on a stack for further verification when a method gets executed on a mock or a method verification takes place.

There's more...

One of the most common mistakes when using argument matchers is that people tend to forget that if you are using a matcher for at least one argument, then you have to provide matchers for all of the arguments. In other words, the following example will result in InvalidUseOfMatchersException (notice that there is an any(...) matcher for the first argument and no matcher for the second argument):

given(irsDataFetcher.isIrsApplicable(any(Person.class), "Warsaw")).willReturn(true);

The following code will work like a charm (notice the any(...) and eq(...) matchers):

given(irsDataFetcher.isIrsApplicable(any(Person.class), eq("Warsaw"))).willReturn(true);

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.145.18.101