package org.mockito.internal.hamcrest; import org.hamcrest.BaseMatcher; import org.hamcrest.Description; import org.hamcrest.Matcher; import org.junit.Test; import org.mockitoutil.TestBase; import java.io.Serializable; import java.util.HashMap; import static junit.framework.TestCase.assertEquals; import static org.mockito.internal.hamcrest.MatcherGenericTypeExtractor.genericTypeOfMatcher; public class MatcherGenericTypeExtractorTest extends TestBase { //traditional inner class for matcher private class IntMatcher extends BaseMatcher<Integer> { public boolean matches(Object o) { return true; } public void describeTo(Description description) {} } //static class with matcher private static class StaticIntMatcher extends BaseMatcher<Integer> { public boolean matches(Object o) { return true; } public void describeTo(Description description) {} } //static subclass private static class StaticIntMatcherSubclass extends StaticIntMatcher { public boolean matches(Object o) { return true; } public void describeTo(Description description) {} } //non-generic @SuppressWarnings("rawtypes") private static class NonGenericMatcher extends BaseMatcher { public boolean matches(Object o) { return true; } public void describeTo(Description description) {} } //Matcher interface implementation (instead of the BaseMatcher) private class IntMatcherFromInterface extends BaseMatcher<Integer> { public boolean matches(Object o) { return true; } public void describeMismatch(Object item, Description mismatchDescription) {} public void describeTo(Description description) {} } //Static Matcher interface implementation (instead of the BaseMatcher) private static class StaticIntMatcherFromInterface extends BaseMatcher<Integer> { public boolean matches(Object o) { return true; } public void describeMismatch(Object item, Description mismatchDescription) {} public void describeTo(Description description) {} } //non-generic matcher implementing the interface @SuppressWarnings("rawtypes") private static class NonGenericMatcherFromInterface extends BaseMatcher { public boolean matches(Object o) { return true; } public void describeMismatch(Object item, Description mismatchDescription) {} public void describeTo(Description description) {} } private interface IMatcher extends Matcher<Integer> {} //non-generic matcher implementing the interface private static class SubclassGenericMatcherFromInterface extends BaseMatcher<Integer> implements Serializable, Cloneable, IMatcher { public boolean matches(Object o) { return true; } public void describeMismatch(Object item, Description mismatchDescription) {} public void describeTo(Description description) {} } //I refuse to comment on the sanity of this case private static class InsaneEdgeCase extends SubclassGenericMatcherFromInterface {} @Test public void findsGenericType() { assertEquals(Integer.class, genericTypeOfMatcher(IntMatcher.class)); assertEquals(Integer.class, genericTypeOfMatcher(StaticIntMatcher.class)); assertEquals(Integer.class, genericTypeOfMatcher(IntMatcherFromInterface.class)); assertEquals(Integer.class, genericTypeOfMatcher(StaticIntMatcherSubclass.class)); assertEquals(Integer.class, genericTypeOfMatcher(IntMatcherFromInterface.class)); assertEquals(Integer.class, genericTypeOfMatcher(StaticIntMatcherFromInterface.class)); assertEquals(Integer.class, genericTypeOfMatcher(SubclassGenericMatcherFromInterface.class)); assertEquals(Integer.class, genericTypeOfMatcher(InsaneEdgeCase.class)); assertEquals(Integer.class, genericTypeOfMatcher(new BaseMatcher<Integer>() { public void describeTo(Description description) { } public boolean matches(Object o) { return false; } }.getClass())); assertEquals(Integer.class, genericTypeOfMatcher(new BaseMatcher<Integer>() { public void describeTo(Description description) { } public boolean matches(Object o) { return false; } public void describeMismatch(Object item, Description mismatchDescription) { } }.getClass())); assertEquals(Object.class, genericTypeOfMatcher(Object.class)); assertEquals(Object.class, genericTypeOfMatcher(String.class)); assertEquals(Object.class, genericTypeOfMatcher(HashMap.class)); assertEquals(Object.class, genericTypeOfMatcher(new HashMap<String, String>() { }.getClass())); assertEquals(Object.class, genericTypeOfMatcher(NonGenericMatcher.class)); assertEquals(Object.class, genericTypeOfMatcher(NonGenericMatcherFromInterface.class)); } }