1   package com.lexicalscope.fluentreflection;
2   
3   import static com.lexicalscope.fluentreflection.ListBuilder.list;
4   import static java.util.Arrays.asList;
5   import static java.util.Collections.emptyList;
6   import static org.hamcrest.MatcherAssert.assertThat;
7   import static org.hamcrest.Matchers.*;
8   
9   import org.hamcrest.Description;
10  import org.hamcrest.Matcher;
11  import org.hamcrest.StringDescription;
12  import org.jmock.Expectations;
13  import org.junit.Rule;
14  import org.junit.Test;
15  
16  public abstract class AbstractTestReflectionMatcher<T> {
17      @Rule public final JUnitRuleMockery context = new JUnitRuleMockery();
18  
19      protected final FluentMethod method = context.mock(FluentMethod.class);
20      protected final FluentConstructor<?> constructor = context.mock(FluentConstructor.class);
21      protected final FluentClass<?> type = context.mock(FluentClass.class);
22      protected final FluentMember callable = context.mock(FluentMember.class);
23      private final Description description = new StringDescription();
24  
25      @Test public final void matcherCanMatch() throws Throwable {
26          setupMatchingCase();
27  
28          assertThat(target(), matcher());
29      }
30  
31      @Test public final void matcherCanFailToMatch() throws Throwable {
32          setupFailingCase();
33  
34          assertThat(failingTarget(), not(matcher()));
35      }
36  
37      @Test public final void matcherDescriptionMakesSense() throws Throwable {
38          assertHasDescription(matcher(), hasDescription());
39      }
40  
41      protected abstract T target();
42  
43      protected abstract Matcher<String> hasDescription();
44  
45      protected void setupMatchingCase() throws Throwable {}
46  
47      protected void setupFailingCase() throws Throwable {}
48  
49      protected abstract ReflectionMatcher<? super T> matcher() throws Throwable;
50  
51      protected T failingTarget() {
52          return target();
53      }
54  
55      protected final void whenMethodHasName(final String methodName) {
56          context.checking(new Expectations() {
57              {
58                  oneOf(method).name();
59                  will(returnValue(methodName));
60              }
61          });
62      }
63  
64      protected final void whenMethodDeclaredBy(final Class<?> declaringClass) {
65          final FluentClass<?> declaringType = context.mock(FluentClass.class, "declaringType");
66          context.checking(new Expectations() {
67              {
68                  oneOf(method).declarer();
69                  will(returnValue(declaringType));
70  
71                  oneOf(declaringType).classUnderReflection();
72                  will(returnValue(declaringClass));
73              }
74          });
75      }
76  
77      protected final void whenMethodHasArguments(final Class<?>... arguments) {
78          final FluentClass<?>[] argumentTypes = new FluentClass<?>[arguments.length];
79          for (int i = 0; i < argumentTypes.length; i++) {
80              argumentTypes[i] =
81                      context.mock(FluentClass.class, "argument " + i + ": " + arguments[i].getSimpleName());
82          }
83  
84          context.checking(new Expectations() {
85              {
86                  oneOf(method).argCount();
87                  will(returnValue(arguments.length));
88  
89                  allowing(method).args();
90                  will(returnValue(asList(argumentTypes)));
91  
92                  for (int i = 0; i < argumentTypes.length; i++) {
93                      allowing(argumentTypes[i]).classUnderReflection();
94                      will(returnValue(arguments[i]));
95                  }
96              }
97          });
98  
99      }
100 
101     protected final void whenTypeHasInterface(final Class<?> interfac3) {
102         final FluentClass<?> interfaceType = context.mock(FluentClass.class, "interfaceType");
103         context.checking(new Expectations() {
104             {
105                 oneOf(type).interfaces();
106                 will(returnValue(list(interfaceType).$()));
107 
108                 allowing(interfaceType).classUnderReflection();
109                 will(returnValue(interfac3));
110             }
111         });
112     }
113 
114     protected final void whenTypeHasSuperclass(final Class<?> klass) {
115         final FluentClass<?> superclassType = context.mock(FluentClass.class, "superclassType");
116         context.checking(new Expectations() {
117             {
118                 oneOf(type).superclasses();
119                 will(returnValue(list(superclassType).$()));
120 
121                 allowing(superclassType).classUnderReflection();
122                 will(returnValue(klass));
123             }
124         });
125     }
126 
127     protected final void whenTypeHasNoSuperclass() {
128         context.checking(new Expectations() {
129             {
130                 oneOf(type).superclasses();
131                 will(returnValue(emptyList()));
132             }
133         });
134     }
135 
136     protected final void whenTypeHasNoInterface() {
137         context.checking(new Expectations() {
138             {
139                 oneOf(type).interfaces();
140                 will(returnValue(emptyList()));
141             }
142         });
143     }
144 
145     protected final void whenTypeIsInterface() {
146         context.checking(new Expectations() {
147             {
148                 oneOf(type).isInterface();
149                 will(returnValue(true));
150             }
151         });
152     }
153 
154     protected final void whenTypeIsNotInterface() {
155         context.checking(new Expectations() {
156             {
157                 oneOf(type).isInterface();
158                 will(returnValue(false));
159             }
160         });
161     }
162 
163     protected final void whenType(final Class<?> klass) {
164         context.checking(new Expectations() {
165             {
166                 oneOf(type).classUnderReflection();
167                 will(returnValue(klass));
168             }
169         });
170     }
171 
172     protected final void assertHasDescription(
173             final ReflectionMatcher<?> matcherUnderTest,
174             final Matcher<String> descriptionMatcher) {
175         matcherUnderTest.describeTo(description);
176         assertThat(description, hasToString(descriptionMatcher));
177     }
178 }