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