/**
* Copyright 2011 Marcin Mikosik
* All rights reserved.
*/
package com.perunlabs.testinjector.util;
import static com.perunlabs.testinjector.util.Reflections.annotatedFields;
import static com.perunlabs.testinjector.util.Reflections.getElementAnnotations;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.fail;
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Set;
import org.junit.Test;
import com.google.inject.BindingAnnotation;
import com.google.inject.name.Named;
import com.perunlabs.testinjector.util.Reflections;
public class ReflectionsTest {
@Test
public void get_field_value_can_read_private_field() throws Exception {
String string = "string";
Field field = ClassWithPrivateField.class.getDeclaredField("field");
ClassWithPrivateField instance = new ClassWithPrivateField();
instance.setField(string);
assertThat(Reflections.getFieldValue(instance, field)).isEqualTo(string);
assertFieldIsNotAccessible(instance, field);
}
class ClassWithPrivateField {
private String field;
public void setField(String value) {
field = value;
}
public String getField() {
return field;
}
}
@Test
public void get_field_value_can_read_private_primitive_field() throws Exception {
int value = 33;
Field field = ClassWithPrivatePrimitiveField.class.getDeclaredField("field");
ClassWithPrivatePrimitiveField instance = new ClassWithPrivatePrimitiveField();
instance.setField(value);
assertThat(Reflections.getFieldValue(instance, field)).isEqualTo(value);
assertFieldIsNotAccessible(instance, field);
}
class ClassWithPrivatePrimitiveField {
private int field;
public void setField(int value) {
field = value;
}
public int getField() {
return field;
}
}
@Test
public void annotated_fields_returns_field_annotated_with_given_annotation() throws Exception {
Set<Field> fields = annotatedFields(ClassWithAnnotatedField.class, Deprecated.class);
assertThat(fields).containsOnly(ClassWithAnnotatedField.class.getField("field"));
}
class ClassWithAnnotatedField {
@Deprecated
public String field;
public String fieldNotAnnotated;
@Named("abc")
public String fieldAnnotatedWithWrongAnnotation;
}
@Test
public void annotated_fields_returns_empty_set_when_no_field_is_annotated() throws Exception {
assertThat(annotatedFields(ClassWithoutAnnotatedFields.class, Deprecated.class)).isEmpty();
}
class ClassWithoutAnnotatedFields {
public String field;
}
@Test
public void get_element_annotations_returns_annotations_of_given_type() throws SecurityException,
NoSuchFieldException {
Class<ClassWithFieldWithManyAnnotations> klass = ClassWithFieldWithManyAnnotations.class;
Field field = klass.getField("field");
List<Annotation> annotations = getElementAnnotations(field, BindingAnnotation.class);
assertThat(annotations).hasSize(2);
assertThat(annotations.get(0).annotationType()).isSameAs(Named.class);
assertThat(annotations.get(1).annotationType()).isSameAs(MyAnnotation.class);
}
class ClassWithFieldWithManyAnnotations {
@Deprecated
@Named("xxx")
@MyAnnotation
public String field;
}
@Test
public void get_element_annotation_returns_empty_set_for_not_annotated_field()
throws SecurityException, NoSuchFieldException {
Class<ClassWithFieldWithoutAnnotations> klass = ClassWithFieldWithoutAnnotations.class;
Field field = klass.getField("field");
List<Annotation> annotations = getElementAnnotations(field, BindingAnnotation.class);
assertThat(annotations).isEmpty();
}
class ClassWithFieldWithoutAnnotations {
public String field;
}
private static void assertFieldIsNotAccessible(Object instance, Field field) {
try {
field.set(instance, "new value");
fail("Field should not be accessible");
} catch (IllegalArgumentException e) {
fail();
} catch (IllegalAccessException e) {
// this is expected
}
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE })
@BindingAnnotation
@interface MyAnnotation {}