Home | History | Annotate | Download | only in hamcrest
      1 /*
      2  * Copyright (c) 2016 Mockito contributors
      3  * This program is made available under the terms of the MIT License.
      4  */
      5 package org.mockito.hamcrest;
      6 
      7 import org.hamcrest.Matcher;
      8 import org.mockito.ArgumentMatcher;
      9 import org.mockito.internal.hamcrest.HamcrestArgumentMatcher;
     10 
     11 import static org.mockito.internal.hamcrest.MatcherGenericTypeExtractor.genericTypeOfMatcher;
     12 import static org.mockito.internal.progress.ThreadSafeMockingProgress.mockingProgress;
     13 import static org.mockito.internal.util.Primitives.defaultValue;
     14 
     15 /**
     16  * Allows matching arguments with hamcrest matchers.
     17  * <b>Requires</b> <a href="http://hamcrest.org/JavaHamcrest/">hamcrest</a> on classpath,
     18  * Mockito <b>does not</b> depend on hamcrest!
     19  * Note the <b>NullPointerException</b> auto-unboxing caveat described below.
     20  * <p/>
     21  * Before implementing or reusing an existing hamcrest matcher please read
     22  * how to deal with sophisticated argument matching in {@link ArgumentMatcher}.
     23  * <p/>
     24  * Mockito 2.1.0 was decoupled from Hamcrest to avoid version incompatibilities
     25  * that have impacted our users in past. Mockito offers a dedicated API to match arguments
     26  * via {@link ArgumentMatcher}.
     27  * Hamcrest integration is provided so that users can take advantage of existing Hamcrest matchers.
     28  * <p/>
     29  * Example:
     30  * <pre>
     31  *     import static org.mockito.hamcrest.MockitoHamcrest.argThat;
     32  *
     33  *     //stubbing
     34  *     when(mock.giveMe(argThat(new MyHamcrestMatcher())));
     35  *
     36  *     //verification
     37  *     verify(mock).giveMe(argThat(new MyHamcrestMatcher()));
     38  * </pre>
     39  * <b>NullPointerException</b> auto-unboxing caveat.
     40  * In rare cases when matching primitive parameter types you <b>*must*</b> use relevant intThat(), floatThat(), etc. method.
     41  * This way you will avoid <code>NullPointerException</code> during auto-unboxing.
     42  * Due to how java works we don't really have a clean way of detecting this scenario and protecting the user from this problem.
     43  * Hopefully, the javadoc describes the problem and solution well.
     44  * If you have an idea how to fix the problem, let us know via the mailing list or the issue tracker.
     45  *
     46  * @since 2.1.0
     47  */
     48 public class MockitoHamcrest {
     49 
     50     /**
     51      * Allows matching arguments with hamcrest matchers.
     52      * <p/>
     53      * See examples in javadoc for {@link MockitoHamcrest} class
     54      *
     55      * @param matcher decides whether argument matches
     56      * @return <code>null</code> or default value for primitive (0, false, etc.)
     57      * @since 2.1.0
     58      */
     59     @SuppressWarnings("unchecked")
     60     public static <T> T argThat(Matcher<T> matcher) {
     61         reportMatcher(matcher);
     62         return  (T) defaultValue(genericTypeOfMatcher(matcher.getClass()));
     63     }
     64 
     65     /**
     66      * Enables integrating hamcrest matchers that match primitive <code>char</code> arguments.
     67      * Note that {@link #argThat} will not work with primitive <code>char</code> matchers due to <code>NullPointerException</code> auto-unboxing caveat.
     68      * <p/>
     69      * See examples in javadoc for {@link MockitoHamcrest} class
     70      *
     71      * @param matcher decides whether argument matches
     72      * @return <code>0</code>.
     73      */
     74     public static char charThat(Matcher<Character> matcher) {
     75         reportMatcher(matcher);
     76         return 0;
     77     }
     78 
     79     /**
     80      * Enables integrating hamcrest matchers that match primitive <code>boolean</code> arguments.
     81      * Note that {@link #argThat} will not work with primitive <code>boolean</code> matchers due to <code>NullPointerException</code> auto-unboxing caveat.
     82      * <p/>
     83      * See examples in javadoc for {@link MockitoHamcrest} class
     84      *
     85      * @param matcher decides whether argument matches
     86      * @return <code>false</code>.
     87      */
     88     public static boolean booleanThat(Matcher<Boolean> matcher) {
     89         reportMatcher(matcher);
     90         return false;
     91     }
     92 
     93     /**
     94      * Enables integrating hamcrest matchers that match primitive <code>byte</code> arguments.
     95      * Note that {@link #argThat} will not work with primitive <code>byte</code> matchers due to <code>NullPointerException</code> auto-unboxing caveat.
     96      * <p/>
     97      * * See examples in javadoc for {@link MockitoHamcrest} class
     98      *
     99      * @param matcher decides whether argument matches
    100      * @return <code>0</code>.
    101      */
    102     public static byte byteThat(Matcher<Byte> matcher) {
    103         reportMatcher(matcher);
    104         return 0;
    105     }
    106 
    107     /**
    108      * Enables integrating hamcrest matchers that match primitive <code>short</code> arguments.
    109      * Note that {@link #argThat} will not work with primitive <code>short</code> matchers due to <code>NullPointerException</code> auto-unboxing caveat.
    110      * <p/>
    111      * * See examples in javadoc for {@link MockitoHamcrest} class
    112      *
    113      * @param matcher decides whether argument matches
    114      * @return <code>0</code>.
    115      */
    116     public static short shortThat(Matcher<Short> matcher) {
    117         reportMatcher(matcher);
    118         return 0;
    119     }
    120 
    121     /**
    122      * Enables integrating hamcrest matchers that match primitive <code>int</code> arguments.
    123      * Note that {@link #argThat} will not work with primitive <code>int</code> matchers due to <code>NullPointerException</code> auto-unboxing caveat.
    124      * <p/>
    125      * * See examples in javadoc for {@link MockitoHamcrest} class
    126      *
    127      * @param matcher decides whether argument matches
    128      * @return <code>0</code>.
    129      */
    130     public static int intThat(Matcher<Integer> matcher) {
    131         reportMatcher(matcher);
    132         return 0;
    133     }
    134 
    135     /**
    136      * Enables integrating hamcrest matchers that match primitive <code>long</code> arguments.
    137      * Note that {@link #argThat} will not work with primitive <code>long</code> matchers due to <code>NullPointerException</code> auto-unboxing caveat.
    138      * <p/>
    139      * * See examples in javadoc for {@link MockitoHamcrest} class
    140      *
    141      * @param matcher decides whether argument matches
    142      * @return <code>0</code>.
    143      */
    144     public static long longThat(Matcher<Long> matcher) {
    145         reportMatcher(matcher);
    146         return 0;
    147     }
    148 
    149     /**
    150      * Enables integrating hamcrest matchers that match primitive <code>float</code> arguments.
    151      * Note that {@link #argThat} will not work with primitive <code>float</code> matchers due to <code>NullPointerException</code> auto-unboxing caveat.
    152      * <p/>
    153      * * See examples in javadoc for {@link MockitoHamcrest} class
    154      *
    155      * @param matcher decides whether argument matches
    156      * @return <code>0</code>.
    157      */
    158     public static float floatThat(Matcher<Float> matcher) {
    159         reportMatcher(matcher);
    160         return 0;
    161     }
    162 
    163     /**
    164      * Enables integrating hamcrest matchers that match primitive <code>double</code> arguments.
    165      * Note that {@link #argThat} will not work with primitive <code>double</code> matchers due to <code>NullPointerException</code> auto-unboxing caveat.
    166      * <p/>
    167      * * See examples in javadoc for {@link MockitoHamcrest} class
    168      *
    169      * @param matcher decides whether argument matches
    170      * @return <code>0</code>.
    171      */
    172     public static double doubleThat(Matcher<Double> matcher) {
    173         reportMatcher(matcher);
    174         return 0;
    175     }
    176 
    177     private static <T> void reportMatcher(Matcher<T> matcher) {
    178         mockingProgress().getArgumentMatcherStorage().reportMatcher(new HamcrestArgumentMatcher<T>(matcher));
    179     }
    180 }
    181