All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.mockito.ArgumentMatcher Maven / Gradle / Ivy

There is a newer version: 5.14.2
Show newest version
/*
 * Copyright (c) 2016 Mockito contributors
 * This program is made available under the terms of the MIT License.
 */
package org.mockito;

/**
 * Allows creating customized argument matchers.
 * This API was changed in Mockito 2.1.0 in an effort to decouple Mockito from Hamcrest
 * and reduce the risk of version incompatibility.
 * Migration guide is included close to the bottom of this javadoc.
 * 

* For non-trivial method arguments used in stubbing or verification, you have the following options * (in no particular order): *

    *
  • refactor the code so that the interactions with collaborators are easier to test with mocks. * Perhaps it is possible to pass a different argument to the method so that mocking is easier? * If stuff is hard to test it usually indicates the design could be better, so do refactor for testability! *
  • *
  • don't match the argument strictly, just use one of the lenient argument matchers like * {@link Mockito#notNull()}. Some times it is better to have a simple test that works than * a complicated test that seem to work. *
  • *
  • implement equals() method in the objects that are used as arguments to mocks. * Mockito naturally uses equals() for argument matching. * Many times, this is option is clean and simple. *
  • *
  • use {@link ArgumentCaptor} to capture the arguments and perform assertions on their state. * Useful when you need to verify the arguments. Captor is not useful if you need argument matching for stubbing. * Many times, this option leads to clean and readable tests with fine-grained validation of arguments. *
  • *
  • use customized argument matchers by implementing {@link ArgumentMatcher} interface * and passing the implementation to the {@link Mockito#argThat} method. * This option is useful if custom matcher is needed for stubbing and can be reused a lot. * Note that {@link Mockito#argThat} demonstrates NullPointerException auto-unboxing caveat. *
  • *
  • use an instance of hamcrest matcher and pass it to * {@link org.mockito.hamcrest.MockitoHamcrest#argThat(org.hamcrest.Matcher)} * Useful if you already have a hamcrest matcher. Reuse and win! * Note that {@link org.mockito.hamcrest.MockitoHamcrest#argThat(org.hamcrest.Matcher)} demonstrates NullPointerException auto-unboxing caveat. *
  • *
  • Java 8 only - use a lambda in place of an {@link ArgumentMatcher} since {@link ArgumentMatcher} * is effectively a functional interface. A lambda can be used with the {@link Mockito#argThat} method.
  • *
* *

* Implementations of this interface can be used with {@link ArgumentMatchers#argThat} method. * Use toString() method for description of the matcher * - it is printed in verification errors. * *


 * class ListOfTwoElements implements ArgumentMatcher<List> {
 *     public boolean matches(List list) {
 *         return list.size() == 2;
 *     }
 *     public String toString() {
 *         //printed in verification errors
 *         return "[list of 2 elements]";
 *     }
 * }
 *
 * List mock = mock(List.class);
 *
 * when(mock.addAll(argThat(new ListOfTwoElements()))).thenReturn(true);
 *
 * mock.addAll(Arrays.asList("one", "two"));
 *
 * verify(mock).addAll(argThat(new ListOfTwoElements()));
 * 
* * To keep it readable you can extract method, e.g: * *

 *   verify(mock).addAll(argThat(new ListOfTwoElements()));
 *   //becomes
 *   verify(mock).addAll(listOfTwoElements());
 * 
* * In Java 8 you can treat ArgumentMatcher as a functional interface * and use a lambda, e.g.: * *

 *   verify(mock).addAll(argThat(list -> list.size() == 2));
 * 
* *

* Read more about other matchers in javadoc for {@link ArgumentMatchers} class. *

2.1.0 migration guide

* * All existing custom implementations of ArgumentMatcher will no longer compile. * All locations where hamcrest matchers are passed to argThat() will no longer compile. * There are 2 approaches to fix the problems: *
    *
  • a) Refactor the hamcrest matcher to Mockito matcher: * Use "implements ArgumentMatcher" instead of "extends ArgumentMatcher". * Then refactor describeTo() method into toString() method. *
  • *
  • * b) Use org.mockito.hamcrest.MockitoHamcrest.argThat() instead of Mockito.argThat(). * Ensure that there is hamcrest dependency on classpath * (Mockito does not depend on hamcrest any more). * *
  • *
* What option is right for you? If you don't mind having a compile-time dependency for Hamcrest, * then the second option is probably right for you. * Your choice should not have a big impact and is fully reversible - * you can choose different option in future (and refactor the code)! * * @param type of argument * @since 2.1.0 */ @FunctionalInterface public interface ArgumentMatcher { /** * Informs if this matcher accepts the given argument. *

* The method should never assert if the argument doesn't match. It * should only return false. *

* See the example in the top level javadoc for {@link ArgumentMatcher} * * @param argument * the argument * @return true if this matcher accepts the given argument. */ boolean matches(T argument); /** * The type of the argument this matcher matches. * *

This method is used to differentiate between a matcher used to match a raw vararg array parameter * from a matcher used to match a single value passed as a vararg parameter. * *

Where the matcher: *

    *
  • is at the parameter index of a vararg parameter
  • *
  • is the last matcher passed
  • *
  • this method returns a type assignable to the vararg parameter's raw type, i.e. its array type.
  • *
* * ...then the matcher is matched against the raw vararg parameter, rather than the first element of the raw parameter. * *

For example: * *


     *  // Given vararg method with signature:
     *  int someVarargMethod(String... args);
     *
     *  // The following will match invocations with any number of parameters, i.e. any number of elements in the raw array.
     *  mock.someVarargMethod(isA(String[].class));
     *
     *  // The following will match invocations with a single parameter, i.e. one string in the raw array.
     *  mock.someVarargMethod(isA(String.class));
     *
     *  // The following will match invocations with two parameters, i.e. two strings in the raw array
     *  mock.someVarargMethod(isA(String.class), isA(String.class));
     * 
* *

Only matcher implementations that can conceptually match a raw vararg parameter should override this method. * * @return the type this matcher handles. The default value of {@link Void} means the type is not known. * @since 4.11.0 */ default Class type() { return Void.class; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy