package com.lexicalscope.fluentreflection.endtoend; import static com.lexicalscope.fluentreflection.FluentReflection.*; import static com.lexicalscope.fluentreflection.ReflectionMatchers.*; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; import org.hamcrest.Matchers; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import com.lexicalscope.fluentreflection.FieldNotFoundException; import com.lexicalscope.fluentreflection.FluentClass; import com.lexicalscope.fluentreflection.FluentField; import com.lexicalscope.fluentreflection.FluentObject; import com.lexicalscope.fluentreflection.ReflectionRuntimeException; /* * Copyright 2012 Tim Wood * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ public class TestReflectedClassFields { @Rule public ExpectedException exception = ExpectedException.none(); public static class Fields { public String publicField; String packageField; protected String field2; private String field3; public static String staticField0; public static final String staticFinalField0 = "value"; public final String finalField0 = "value"; } @Test public void canFindFieldByName() throws SecurityException, NoSuchFieldException { assertThat( type(Fields.class).fields(hasName("publicField")), contains(isReflectingOnField(Fields.class.getDeclaredField("publicField")))); } @Test public void canNotFindStaticFieldOfBoundObject() throws SecurityException, NoSuchFieldException { assertThat( object(new Fields()).fields(hasName("staticField0")), Matchers.<FluentField>empty()); } @Test public void canWriteField() throws SecurityException, NoSuchFieldException { final FluentObject<Fields> object = object(new Fields()); final FluentField field = object.field(hasName("publicField")); field.call("value"); assertThat( field.call().value(), equalTo((Object) "value")); } @Test public void fieldDeclaringTypeIsCorrect() throws SecurityException, NoSuchFieldException { assertThat( type(Fields.class).field(hasName("publicField")), declaredBy(Fields.class)); } @Test public void finalFieldsAreMarkedAsFinal() throws SecurityException, NoSuchFieldException { assertThat( type(Fields.class).field(hasName("finalField0")), isFinal()); } @Test public void propertyNameIsAvailable() throws SecurityException, NoSuchFieldException { assertThat( type(Fields.class).field(hasName("publicField")), hasName("publicField").and(hasPropertyName("publicField"))); } @Test public void fieldHasZeroArgument() throws SecurityException, NoSuchFieldException { assertThat( type(Fields.class).field(hasName("publicField")), hasArgumentCount(0)); } @Test public void publicFieldToStringIsUseful() throws SecurityException, NoSuchFieldException { assertThat( type(Fields.class).field(hasName("publicField")), hasToString("public java.lang.String publicField")); } @Test public void packageToStringIsUseful() throws SecurityException, NoSuchFieldException { assertThat( type(Fields.class).field(hasName("packageField")), hasToString("java.lang.String packageField")); } @Test public void staticToStringIsUseful() throws SecurityException, NoSuchFieldException { assertThat( type(Fields.class).field(hasName("staticField0")), hasToString("public static java.lang.String staticField0")); } @Test public void staticFinalToStringIsUseful() throws SecurityException, NoSuchFieldException { assertThat( type(Fields.class).field(hasName("staticFinalField0")), hasToString("public static final java.lang.String staticFinalField0")); } @Test public void boundToStringIsUseful() throws SecurityException, NoSuchFieldException { assertThat( object(new Fields()).field(hasName("publicField")), hasToString(startsWith("public java.lang.String publicField"))); } @Test public void boundEqualsIsTrueForTheSameInstance() throws SecurityException, NoSuchFieldException { final Fields instance = new Fields(); assertThat( object(instance).field(hasName("publicField")), equalTo(object(instance).field(hasName("publicField")))); } @Test public void hashCodeIsTheSameForTheSameBoundInstance() throws SecurityException, NoSuchFieldException { final Fields instance = new Fields(); assertThat( object(instance).field(hasName("publicField")).hashCode(), equalTo(object(instance).field(hasName("publicField")).hashCode())); } @Test public void boundEqualsIsFalseForTheDifferentBoundInstances() throws SecurityException, NoSuchFieldException { assertThat( object(new Fields()).field(hasName("publicField")), not(equalTo(object(new Fields()).field(hasName("publicField"))))); } @Test public void equalsIsTrueWhenTheFieldsAreTheSameAsEachOther() throws SecurityException, NoSuchFieldException { final FluentField field = object(new Fields()).field(hasName("publicField")); assertThat(field, equalTo(field)); } @Test public void equalsIsTrueWhenTheThatIsARandomOtherObject() throws SecurityException, NoSuchFieldException { final FluentField field = object(new Fields()).field(hasName("publicField")); assertThat(field, not(equalTo(new Object()))); } @Test public void cannotReadFieldWithoutInstance() throws SecurityException, NoSuchFieldException { final FluentClass<Fields> object = type(Fields.class); final FluentField field = object.field(hasName("publicField")); exception.expect(ReflectionRuntimeException.class); exception.expectMessage("reading a field requires an instance argument"); field.call(); } @Test public void cannotCallFieldWithTooManyArguments() throws SecurityException, NoSuchFieldException { final FluentClass<Fields> object = type(Fields.class); final FluentField field = object.field(hasName("publicField")); exception.expect(ReflectionRuntimeException.class); exception.expectMessage("reading a field requires one argument, writing a field requires two arguments. Got 3 arguments"); field.call(new Fields(), "value", "excess argument"); } @Test public void missingFieldThrowsException() throws SecurityException, NoSuchFieldException { exception.expect(FieldNotFoundException.class); object(new Fields()).field(hasName("noSuchField")); } }