1   package com.lexicalscope.fluentreflection.endtoend;
2   
3   import static com.lexicalscope.fluentreflection.FluentReflection.*;
4   import static com.lexicalscope.fluentreflection.ReflectionMatchers.*;
5   import static org.hamcrest.MatcherAssert.assertThat;
6   import static org.hamcrest.Matchers.*;
7   
8   import org.hamcrest.Matchers;
9   import org.junit.Rule;
10  import org.junit.Test;
11  import org.junit.rules.ExpectedException;
12  
13  import com.lexicalscope.fluentreflection.FieldNotFoundException;
14  import com.lexicalscope.fluentreflection.FluentClass;
15  import com.lexicalscope.fluentreflection.FluentField;
16  import com.lexicalscope.fluentreflection.FluentObject;
17  import com.lexicalscope.fluentreflection.ReflectionRuntimeException;
18  
19  
20  /*
21   * Copyright 2012 Tim Wood
22   *
23   * Licensed under the Apache License, Version 2.0 (the "License");
24   * you may not use this file except in compliance with the License.
25   * You may obtain a copy of the License at
26   *
27   * http://www.apache.org/licenses/LICENSE-2.0
28   *
29   * Unless required by applicable law or agreed to in writing, software
30   * distributed under the License is distributed on an "AS IS" BASIS,
31   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
32   * See the License for the specific language governing permissions and
33   * limitations under the License.
34   */
35  
36  public class TestReflectedClassFields {
37      @Rule public ExpectedException exception = ExpectedException.none();
38  
39      public static class Fields {
40          public String publicField;
41          String packageField;
42          protected String field2;
43          private String field3;
44          public static String staticField0;
45          public static final String staticFinalField0 = "value";
46          public final String finalField0 = "value";
47      }
48  
49      @Test public void canFindFieldByName() throws SecurityException, NoSuchFieldException {
50          assertThat(
51                  type(Fields.class).fields(hasName("publicField")),
52                  contains(isReflectingOnField(Fields.class.getDeclaredField("publicField"))));
53      }
54  
55      @Test public void canNotFindStaticFieldOfBoundObject() throws SecurityException, NoSuchFieldException {
56          assertThat(
57                  object(new Fields()).fields(hasName("staticField0")),
58                  Matchers.<FluentField>empty());
59      }
60  
61      @Test public void canWriteField() throws SecurityException, NoSuchFieldException {
62          final FluentObject<Fields> object = object(new Fields());
63          final FluentField field = object.field(hasName("publicField"));
64  
65          field.callRaw("value");
66          assertThat(
67                  field.callRaw(),
68                  equalTo((Object) "value"));
69      }
70  
71      @Test public void fieldDeclaringTypeIsCorrect() throws SecurityException, NoSuchFieldException {
72          assertThat(
73                  type(Fields.class).field(hasName("publicField")),
74                  declaredBy(Fields.class));
75      }
76  
77      @Test public void finalFieldsAreMarkedAsFinal() throws SecurityException, NoSuchFieldException {
78          assertThat(
79                  type(Fields.class).field(hasName("finalField0")),
80                  isFinal());
81      }
82  
83      @Test public void propertyNameIsAvailable() throws SecurityException, NoSuchFieldException {
84          assertThat(
85                  type(Fields.class).field(hasName("publicField")),
86                  hasName("publicField").and(hasPropertyName("publicField")));
87      }
88  
89      @Test public void fieldHasOneArgument() throws SecurityException, NoSuchFieldException {
90          assertThat(
91                  type(Fields.class).field(hasName("publicField")),
92                  hasArgumentCount(1));
93      }
94  
95      @Test public void publicFieldToStringIsUseful() throws SecurityException, NoSuchFieldException {
96          assertThat(
97                  type(Fields.class).field(hasName("publicField")),
98                  hasToString("public java.lang.String publicField"));
99      }
100 
101     @Test public void packageToStringIsUseful() throws SecurityException, NoSuchFieldException {
102         assertThat(
103                 type(Fields.class).field(hasName("packageField")),
104                 hasToString("java.lang.String packageField"));
105     }
106 
107     @Test public void staticToStringIsUseful() throws SecurityException, NoSuchFieldException {
108         assertThat(
109                 type(Fields.class).field(hasName("staticField0")),
110                 hasToString("public static java.lang.String staticField0"));
111     }
112 
113     @Test public void staticFinalToStringIsUseful() throws SecurityException, NoSuchFieldException {
114         assertThat(
115                 type(Fields.class).field(hasName("staticFinalField0")),
116                 hasToString("public static final java.lang.String staticFinalField0"));
117     }
118 
119     @Test public void boundToStringIsUseful() throws SecurityException, NoSuchFieldException {
120         assertThat(
121                 object(new Fields()).field(hasName("publicField")),
122                 hasToString(startsWith("public java.lang.String publicField")));
123     }
124 
125     @Test public void boundEqualsIsTrueForTheSameInstance() throws SecurityException, NoSuchFieldException {
126         final Fields instance = new Fields();
127         assertThat(
128                 object(instance).field(hasName("publicField")),
129                 equalTo(object(instance).field(hasName("publicField"))));
130     }
131 
132     @Test public void hashCodeIsTheSameForTheSameBoundInstance() throws SecurityException, NoSuchFieldException {
133         final Fields instance = new Fields();
134         assertThat(
135                 object(instance).field(hasName("publicField")).hashCode(),
136                 equalTo(object(instance).field(hasName("publicField")).hashCode()));
137     }
138 
139     @Test public void boundEqualsIsFalseForTheDifferentBoundInstances() throws SecurityException, NoSuchFieldException {
140         assertThat(
141                 object(new Fields()).field(hasName("publicField")),
142                 not(equalTo(object(new Fields()).field(hasName("publicField")))));
143     }
144 
145     @Test public void equalsIsTrueWhenTheFieldsAreTheSameAsEachOther() throws SecurityException, NoSuchFieldException {
146         final FluentField field = object(new Fields()).field(hasName("publicField"));
147         assertThat(field, equalTo(field));
148     }
149 
150     @Test public void equalsIsTrueWhenTheThatIsARandomOtherObject() throws SecurityException, NoSuchFieldException {
151         final FluentField field = object(new Fields()).field(hasName("publicField"));
152         assertThat(field, not(equalTo(new Object())));
153     }
154 
155     @Test public void cannotReadFieldWithoutInstance() throws SecurityException, NoSuchFieldException {
156         final FluentClass<Fields> object = type(Fields.class);
157         final FluentField field = object.field(hasName("publicField"));
158 
159         exception.expect(ReflectionRuntimeException.class);
160         exception.expectMessage("reading a field requires an instance argument");
161         field.callRaw();
162     }
163 
164     @Test public void cannotCallFieldWithTooManyArguments() throws SecurityException, NoSuchFieldException {
165         final FluentClass<Fields> object = type(Fields.class);
166         final FluentField field = object.field(hasName("publicField"));
167 
168         exception.expect(ReflectionRuntimeException.class);
169         exception.expectMessage("reading a field requires one argument, writing a field requires two arguments. Got 3 arguments");
170         field.callRaw(new Fields(), "value", "excess argument");
171     }
172 
173     @Test public void missingFieldThrowsException() throws SecurityException, NoSuchFieldException {
174         exception.expect(FieldNotFoundException.class);
175         object(new Fields()).field(hasName("noSuchField"));
176     }
177 }