TypeSafeMatchingTest.java revision 2637d96c202372854a7c71466ddcc6e90fc4fc53
1package org.mockito.internal.invocation;
2
3import static org.assertj.core.api.Assertions.assertThat;
4import static org.mockito.internal.invocation.TypeSafeMatching.matchesTypeSafe;
5
6import java.util.Date;
7import java.util.concurrent.atomic.AtomicBoolean;
8
9import org.junit.Rule;
10import org.junit.Test;
11import org.mockito.ArgumentMatcher;
12import org.mockito.Mock;
13import org.mockito.internal.matchers.LessOrEqual;
14import org.mockito.internal.matchers.Null;
15import org.mockito.internal.matchers.StartsWith;
16import org.mockito.junit.MockitoJUnit;
17import org.mockito.junit.MockitoRule;
18import org.mockitousage.IMethods;
19
20public class TypeSafeMatchingTest {
21
22    private static final Object NOT_A_COMPARABLE = new Object();
23
24    @Rule
25    public MockitoRule mockitoRule = MockitoJUnit.rule();
26
27    @Mock
28    public IMethods mock;
29
30    /**
31     * Should not throw an {@link NullPointerException}
32     *
33     * @see Bug-ID https://github.com/mockito/mockito/issues/457
34     */
35    @Test
36    public void compareNullArgument() {
37        boolean match = matchesTypeSafe().apply(new LessOrEqual<Integer>(5), null);
38        assertThat(match).isFalse();
39
40    }
41
42    /**
43     * Should not throw an {@link ClassCastException}
44     */
45    @Test
46    public void compareToNonCompareable() {
47        boolean match = matchesTypeSafe().apply(new LessOrEqual<Integer>(5), NOT_A_COMPARABLE);
48        assertThat(match).isFalse();
49    }
50
51    /**
52     * Should not throw an {@link ClassCastException}
53     */
54    @Test
55    public void compareToNull() {
56        boolean match = matchesTypeSafe().apply(new LessOrEqual<Integer>(null), null);
57        assertThat(match).isFalse();
58    }
59
60    /**
61     * Should not throw an {@link ClassCastException}
62     */
63    @Test
64    public void compareToNull2() {
65        boolean match = matchesTypeSafe().apply(Null.NULL, null);
66        assertThat(match).isTrue();
67    }
68
69    /**
70     * Should not throw an {@link ClassCastException}
71     */
72    @Test
73    public void compareToStringVsInt() {
74        boolean match = matchesTypeSafe().apply(new StartsWith("Hello"), 123);
75        assertThat(match).isFalse();
76    }
77
78    @Test
79    public void compareToIntVsString() throws Exception {
80        boolean match = matchesTypeSafe().apply(new LessOrEqual<Integer>(5), "Hello");
81        assertThat(match).isFalse();
82    }
83
84    @Test
85    public void matchesOverloadsMustBeIgnored() {
86        class TestMatcher implements ArgumentMatcher<Integer> {
87            @Override
88            public boolean matches(Integer arg) {
89                return false;
90            }
91
92            @SuppressWarnings("unused")
93            public boolean matches(Date arg) {
94                throw new UnsupportedOperationException();
95            }
96
97            @SuppressWarnings("unused")
98            public boolean matches(Integer arg, Void v) {
99                throw new UnsupportedOperationException();
100            }
101
102        }
103
104        boolean match = matchesTypeSafe().apply(new TestMatcher(), 123);
105        assertThat(match).isFalse();
106    }
107
108    @Test
109    public void matchesWithSubTypeExtendingGenericClass() {
110        abstract class GenericMatcher<T> implements ArgumentMatcher<T> {
111        }
112        class TestMatcher extends GenericMatcher<Integer> {
113            @Override
114            public boolean matches(Integer argument) {
115                return true;
116            }
117        }
118        boolean match = matchesTypeSafe().apply(new TestMatcher(), 123);
119        assertThat(match).isTrue();
120    }
121
122    @Test
123    public void dontMatchesWithSubTypeExtendingGenericClass() {
124        final AtomicBoolean wasCalled = new AtomicBoolean();
125
126        abstract class GenericMatcher<T> implements ArgumentMatcher<T> {
127        }
128        class TestMatcher extends GenericMatcher<Integer> {
129            @Override
130            public boolean matches(Integer argument) {
131                wasCalled.set(true);
132                return true;
133            }
134        }
135        wasCalled.set(false);
136        matchesTypeSafe().apply(new TestMatcher(), 123);
137        assertThat(wasCalled.get()).isTrue();
138
139        wasCalled.set(false);
140        matchesTypeSafe().apply(new TestMatcher(), "");
141        assertThat(wasCalled.get()).isFalse();
142    }
143
144    @Test
145    public void passEveryArgumentTypeIfNoBridgeMethodWasGenerated() {
146        final AtomicBoolean wasCalled = new AtomicBoolean();
147        class GenericMatcher<T> implements ArgumentMatcher<T> {
148            @Override
149            public boolean matches(T argument) {
150                wasCalled.set(true);
151                return true;
152            }
153        }
154
155        wasCalled.set(false);
156        matchesTypeSafe().apply(new GenericMatcher<Integer>(), 123);
157        assertThat(wasCalled.get()).isTrue();
158
159        wasCalled.set(false);
160        matchesTypeSafe().apply(new GenericMatcher<Integer>(), "");
161        assertThat(wasCalled.get()).isTrue();
162    }
163}
164