Skip to content

Commit

Permalink
Draft: Organize test fixtures, add documentation where needed
Browse files Browse the repository at this point in the history
  • Loading branch information
GuusLieben committed Dec 17, 2024
1 parent 0f301ba commit ea3d387
Show file tree
Hide file tree
Showing 42 changed files with 473 additions and 171 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
import org.dockbox.hartshorn.util.introspect.annotations.VirtualHierarchyAnnotationLookup;
import org.dockbox.hartshorn.util.introspect.reflect.ReflectionIntrospector;

import test.org.dockbox.hartshorn.util.introspect.convert.ConversionServiceTests;

public class ReflectionConversionServiceTests extends ConversionServiceTests {
@Override
protected Introspector introspector() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import org.dockbox.hartshorn.util.introspect.reflect.ReflectionIntrospector;
import org.junit.jupiter.api.BeforeEach;

public class ReflectionElementContextTests extends ElementContextTests {
public class ReflectionTypeIntrospectionTests extends TypeIntrospectionTests {

private Introspector introspector;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@

package org.dockbox.hartshorn.util.introspect.convert;

/**
* Accessor to expose the {@link Null} instance, which is otherwise only accessible to the converter package
* for internal usage.
*
* @author Guus Lieben
*
* @since 0.7.0
*/
public class NullAccess {

public static Null getInstance() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package test.org.dockbox.hartshorn.util.introspect.convert;
package test.org.dockbox.hartshorn.util.introspect;

import java.util.LinkedList;
import java.util.List;
Expand All @@ -37,7 +37,16 @@
import org.dockbox.hartshorn.util.option.Option;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import test.org.dockbox.hartshorn.util.introspect.support.basic.TestEnumType;

/**
* Tests for the {@link ConversionService} interface, driven by configurable {@link Introspector}
* implementations.
*
* @since 0.7.0
*
* @author Guus Lieben
*/
public abstract class ConversionServiceTests {

protected abstract Introspector introspector();
Expand All @@ -46,10 +55,6 @@ protected ConversionService conversionService() {
return new StandardConversionService(this.introspector()).withDefaults();
}

enum DemoABC {
A, B, C,
}

@Test
void testPrimitiveWrapperFromEmptyString() {
ConversionService conversionService = this.conversionService();
Expand All @@ -76,11 +81,11 @@ void testPrimitiveFromString() {
@Test
void testEnumFromString() {
ConversionService conversionService = this.conversionService();
DemoABC a = conversionService.convert("A", DemoABC.class);
TestEnumType a = conversionService.convert("A", TestEnumType.class);
Assertions.assertNotNull(a);
Assertions.assertSame(DemoABC.A, a);
Assertions.assertSame(TestEnumType.A, a);

DemoABC d = conversionService.convert("D", DemoABC.class);
TestEnumType d = conversionService.convert("D", TestEnumType.class);
Assertions.assertNull(d);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,23 @@
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

import test.org.dockbox.hartshorn.util.introspect.support.annotated.AnnotatedObject;
import test.org.dockbox.hartshorn.util.introspect.support.annotations.AnyElementAnnotation;
import test.org.dockbox.hartshorn.util.introspect.support.annotations.MultipleElementAnnotation;
import test.org.dockbox.hartshorn.util.introspect.support.basic.ConcreteTestType;
import test.org.dockbox.hartshorn.util.introspect.support.basic.ParentTestType;
import test.org.dockbox.hartshorn.util.introspect.support.basic.TestEnumType;
import test.org.dockbox.hartshorn.util.introspect.support.bridge.BridgeElement;

/**
* Tests for the {@link Introspector} interface. Unlike {@link TypeIntrospectionTests}, this class
* focuses more on the complex implementations of the {@link Introspector} interface, rather than
* basic type information.
*
* @since 0.7.0
*
* @author Guus Lieben
*/
public abstract class IntrospectorTests {

private static Stream<Arguments> fields() {
Expand Down Expand Up @@ -117,8 +133,8 @@ private static Stream<Arguments> primitiveValues() {
@ParameterizedTest
@MethodSource("fields")
void testFieldValueReturnsValue(String field) throws Throwable {
ReflectTestType instance = new ReflectTestType();
TypeView<ReflectTestType> type = this.introspector().introspect(instance);
ConcreteTestType instance = new ConcreteTestType();
TypeView<ConcreteTestType> type = this.introspector().introspect(instance);
Option<?> value = type.fields().named(field).get().get(instance);
Assertions.assertTrue(value.present());
Assertions.assertEquals(field, value.get());
Expand All @@ -127,8 +143,8 @@ void testFieldValueReturnsValue(String field) throws Throwable {
@ParameterizedTest
@MethodSource("methods")
void testRunMethodReturnsValue(String method) throws Throwable {
ReflectTestType instance = new ReflectTestType();
TypeView<ReflectTestType> type = this.introspector().introspect(instance);
ConcreteTestType instance = new ConcreteTestType();
TypeView<ConcreteTestType> type = this.introspector().introspect(instance);
Option<?> value = type.methods().named(method, List.of(String.class)).get().invoke(instance, "value");
Assertions.assertTrue(value.present());
Assertions.assertEquals("VALUE", value.get());
Expand All @@ -145,23 +161,23 @@ void testAssignableFromPrimitives(Class<?> primitive, Class<?> wrapper) {

@Test
void testAssignableFromSuper() {
Assertions.assertTrue(this.introspector().introspect(ReflectTestType.class).isChildOf(ParentTestType.class));
Assertions.assertTrue(this.introspector().introspect(ConcreteTestType.class).isChildOf(ParentTestType.class));
}

@Test
void testAssignableFromSame() {
Assertions.assertTrue(this.introspector().introspect(ReflectTestType.class).isChildOf(ReflectTestType.class));
Assertions.assertTrue(this.introspector().introspect(ConcreteTestType.class).isChildOf(ConcreteTestType.class));
}

@Test
void testAssignableFromChild() {
Assertions.assertFalse(this.introspector().introspect(ParentTestType.class).isChildOf(ReflectTestType.class));
Assertions.assertFalse(this.introspector().introspect(ParentTestType.class).isChildOf(ConcreteTestType.class));
}

@Test
void testAnnotatedMethodsReturnsAllModifiers() {
TypeView<ReflectTestType> type = this.introspector().introspect(ReflectTestType.class);
List<MethodView<ReflectTestType, ?>> methods = type.methods().annotatedWith(Demo.class);
TypeView<ConcreteTestType> type = this.introspector().introspect(ConcreteTestType.class);
List<MethodView<ConcreteTestType, ?>> methods = type.methods().annotatedWith(MultipleElementAnnotation.class);
Assertions.assertEquals(3, methods.size());

List<String> names = methods.stream().map(MethodView::name).toList();
Expand All @@ -171,34 +187,34 @@ void testAnnotatedMethodsReturnsAllModifiers() {

@Test
void testStaticFieldsReturnsAllModifiers() {
List<FieldView<ReflectTestType, ?>> fields = this.introspector().introspect(ReflectTestType.class).fields().all().stream()
List<FieldView<ConcreteTestType, ?>> fields = this.introspector().introspect(ConcreteTestType.class).fields().all().stream()
.filter(field -> field.modifiers().isStatic())
.toList();
Assertions.assertEquals(2, fields.size());
}

@Test
void testHasAnnotationOnMethod() {
Option<MethodView<ReflectTestType, ?>> method = this.introspector().introspect(ReflectTestType.class)
Option<MethodView<ConcreteTestType, ?>> method = this.introspector().introspect(ConcreteTestType.class)
.methods()
.named("publicAnnotatedMethod");
Assertions.assertTrue(method.present());
Assertions.assertTrue(method.get().annotations().has(Demo.class));
Assertions.assertTrue(method.get().annotations().has(MultipleElementAnnotation.class));
}

@Test
void testSuperTypesReturnsAllSuperTypesWithoutObject() {
TypeView<?> parent = this.introspector().introspect(ReflectTestType.class).superClass();
TypeView<?> parent = this.introspector().introspect(ConcreteTestType.class).superClass();
Assertions.assertFalse(parent.isVoid());
Assertions.assertSame(ParentTestType.class, parent.type());
}

@Test
void testMethodsReturnsAllDeclaredAndParentMethods() {
TypeView<ReflectTestType> type = this.introspector().introspect(ReflectTestType.class);
List<MethodView<ReflectTestType, ?>> methods = type.methods().all();
TypeView<ConcreteTestType> type = this.introspector().introspect(ConcreteTestType.class);
List<MethodView<ConcreteTestType, ?>> methods = type.methods().all();
boolean fail = true;
for (MethodView<ReflectTestType, ?> method : methods) {
for (MethodView<ConcreteTestType, ?> method : methods) {
if ("parentMethod".equals(method.name())) {
fail = false;
}
Expand Down Expand Up @@ -231,9 +247,9 @@ void testTypeContextBridgeMethodsCanBeObtained() {

@Test
void testLookupReturnsClassIfPresent() {
TypeView<?> lookup = this.introspector().introspect(ReflectTestType.class.getName());
TypeView<?> lookup = this.introspector().introspect(ConcreteTestType.class.getName());
Assertions.assertNotNull(lookup);
Assertions.assertSame(ReflectTestType.class, lookup.type());
Assertions.assertSame(ConcreteTestType.class, lookup.type());
}

@Test
Expand All @@ -244,31 +260,31 @@ void testLookupReturnsVoidIfAbsent() {

@Test
void testHasMethodIsTrueIfMethodExists() {
Assertions.assertTrue(this.introspector().introspect(ReflectTestType.class)
Assertions.assertTrue(this.introspector().introspect(ConcreteTestType.class)
.methods()
.named("publicMethod", String.class)
.present());
}

@Test
void testHasMethodIsFalseIfMethodDoesNotExist() {
Assertions.assertFalse(this.introspector().introspect(ReflectTestType.class)
Assertions.assertFalse(this.introspector().introspect(ConcreteTestType.class)
.methods()
.named("otherMethod")
.present());
}

@Test
void testInstanceHasMethodIsTrueIfMethodExists() {
Assertions.assertTrue(this.introspector().introspect(new ReflectTestType())
Assertions.assertTrue(this.introspector().introspect(new ConcreteTestType())
.methods()
.named("publicMethod", String.class)
.present());
}

@Test
void testInstanceHasMethodIsFalseIfMethodDoesNotExist() {
Assertions.assertFalse(this.introspector().introspect(new ReflectTestType())
Assertions.assertFalse(this.introspector().introspect(new ConcreteTestType())
.methods()
.named("otherMethod")
.present());
Expand All @@ -293,7 +309,7 @@ void testVoidIsTrueIfTypeIsVoidPrimitive() {
@ParameterizedTest
@MethodSource("fields")
void testHasFieldReturnsTrue(String field) {
Assertions.assertTrue(this.introspector().introspect(ReflectTestType.class)
Assertions.assertTrue(this.introspector().introspect(ConcreteTestType.class)
.fields()
.named(field)
.present());
Expand All @@ -303,8 +319,8 @@ void testHasFieldReturnsTrue(String field) {
@MethodSource("fields")
void testFieldsConsumesAllFields(String field) {
boolean activated = false;
TypeView<ReflectTestType> type = this.introspector().introspect(ReflectTestType.class);
for (FieldView<ReflectTestType, ?> fieldView : type.fields().all()) {
TypeView<ConcreteTestType> type = this.introspector().introspect(ConcreteTestType.class);
for (FieldView<ConcreteTestType, ?> fieldView : type.fields().all()) {
if (fieldView.name().equals(field)) {
activated = true;
}
Expand All @@ -314,30 +330,31 @@ void testFieldsConsumesAllFields(String field) {

@Test
void testSetFieldUpdatesAccessorField() throws Throwable {
Field fieldRef = ReflectTestType.class.getDeclaredField("accessorField");
Field fieldRef = ConcreteTestType.class.getDeclaredField("accessorField");
FieldView<?, ?> field = this.introspector().introspect(fieldRef);
ReflectTestType instance = new ReflectTestType();
ConcreteTestType instance = new ConcreteTestType();
field.set(instance, "newValue");

Assertions.assertTrue(instance.activatedSetter());
}

@Test
void testSetFieldUpdatesNormalField() throws Throwable {
Field fieldRef = ReflectTestType.class.getDeclaredField("publicField");
Field fieldRef = ConcreteTestType.class.getDeclaredField("publicField");
FieldView<?, ?> field = this.introspector().introspect(fieldRef);
ReflectTestType instance = new ReflectTestType();
ConcreteTestType instance = new ConcreteTestType();
field.set(instance, "newValue");

Assertions.assertEquals("newValue", instance.publicField);
}

@Test
void testAnnotatedFieldsIncludesStatic() {
List<FieldView<ReflectTestType, ?>> fields = this.introspector().introspect(ReflectTestType.class).fields().annotatedWith(Demo.class);
List<FieldView<ConcreteTestType, ?>> fields = this.introspector().introspect(ConcreteTestType.class).fields().annotatedWith(
MultipleElementAnnotation.class);
Assertions.assertEquals(2, fields.size());
int statics = 0;
for (FieldView<ReflectTestType, ?> field : fields) {
for (FieldView<ConcreteTestType, ?> field : fields) {
if (field.modifiers().isStatic()) {
statics++;
}
Expand All @@ -347,8 +364,8 @@ void testAnnotatedFieldsIncludesStatic() {

@Test
void testAnnotatedConstructors() {
TypeView<ReflectTestType> type = this.introspector().introspect(ReflectTestType.class);
List<ConstructorView<ReflectTestType>> constructors = type.constructors().annotatedWith(Demo.class);
TypeView<ConcreteTestType> type = this.introspector().introspect(ConcreteTestType.class);
List<ConstructorView<ConcreteTestType>> constructors = type.constructors().annotatedWith(MultipleElementAnnotation.class);
Assertions.assertEquals(1, constructors.size());
}

Expand All @@ -363,7 +380,7 @@ void testStringToPrimitive(Class<?> type, String value, Object expected) throws
@Test
void testRedefinedAnnotationsTakePriority() {
TypeView<AnnotatedObject> typeContext = this.introspector().introspect(AnnotatedObject.class);
Option<Base> annotation = typeContext.annotations().get(Base.class);
Option<AnyElementAnnotation> annotation = typeContext.annotations().get(AnyElementAnnotation.class);
Assertions.assertTrue(annotation.present());
Assertions.assertEquals("impl", annotation.get().value());
}
Expand Down

This file was deleted.

Loading

0 comments on commit ea3d387

Please sign in to comment.