• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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")
argThat(Matcher<T> matcher)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      */
charThat(Matcher<Character> matcher)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      */
booleanThat(Matcher<Boolean> matcher)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      */
byteThat(Matcher<Byte> matcher)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      */
shortThat(Matcher<Short> matcher)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      */
intThat(Matcher<Integer> matcher)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      */
longThat(Matcher<Long> matcher)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      */
floatThat(Matcher<Float> matcher)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      */
doubleThat(Matcher<Double> matcher)172     public static double doubleThat(Matcher<Double> matcher) {
173         reportMatcher(matcher);
174         return 0;
175     }
176 
reportMatcher(Matcher<T> matcher)177     private static <T> void reportMatcher(Matcher<T> matcher) {
178         mockingProgress().getArgumentMatcherStorage().reportMatcher(new HamcrestArgumentMatcher<T>(matcher));
179     }
180 }
181