/* * 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. * <p> * For non-trivial method arguments used in stubbing or verification, you have following options * (in no particular order): * <ul> * <li>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! * </li> * <li>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. * </li> * <li>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. * </li> * <li>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. * </li> * <li>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 <b>NullPointerException</b> auto-unboxing caveat. * </li> * <li>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 <b>NullPointerException</b> auto-unboxing caveat. * </li> * <li>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.</li> * </ul> * * <p> * Implementations of this interface can be used with {@link Matchers#argThat} method. * Use <code>toString()</code> method for description of the matcher * - it is printed in verification errors. * * <pre class="code"><code class="java"> * 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())); * </code></pre> * * To keep it readable you can extract method, e.g: * * <pre class="code"><code class="java"> * verify(mock).addAll(<b>argThat(new ListOfTwoElements())</b>); * //becomes * verify(mock).addAll(<b>listOfTwoElements()</b>); * </code></pre> * * In Java 8 you can treat ArgumentMatcher as a functional interface * and use a lambda, e.g.: * * <pre class="code"><code class="java"> * verify(mock).addAll(<b>argThat(list -> list.size() == 2)</b>); * </code></pre> * * <p> * Read more about other matchers in javadoc for {@link Matchers} class. * <h2>2.1.0 migration guide</h2> * * All existing custom implementations of <code>ArgumentMatcher</code> will no longer compile. * All locations where hamcrest matchers are passed to <code>argThat()</code> will no longer compile. * There are 2 approaches to fix the problems: * <ul> * <li>a) Refactor the hamcrest matcher to Mockito matcher: * Use "implements ArgumentMatcher" instead of "extends ArgumentMatcher". * Then refactor <code>describeTo()</code> method into <code>toString()</code> method. * </li> * <li> * b) Use <code>org.mockito.hamcrest.MockitoHamcrest.argThat()</code> instead of <code>Mockito.argThat()</code>. * Ensure that there is <a href="http://hamcrest.org/JavaHamcrest/">hamcrest</a> dependency on classpath * (Mockito does not depend on hamcrest any more). * * </li> * </ul> * What option is right for you? If you don't mind compile dependency to hamcrest * then option b) is probably right for you. * Your choice should not have big impact and is fully reversible - * you can choose different option in future (and refactor the code) * * @param <T> type of argument * @since 2.1.0 */ public interface ArgumentMatcher<T> { /** * Informs if this matcher accepts the given argument. * <p> * The method should <b>never</b> assert if the argument doesn't match. It * should only return false. * <p> * 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); }