From b11da4da172e741603b18328e18f72b8df3d10ef Mon Sep 17 00:00:00 2001 From: Andreas Kutschera Date: Thu, 12 Sep 2024 18:08:00 +0200 Subject: [PATCH 1/2] experiment: add 'with' method to builders. If you want to configure a builder, you could do it like this. It would be cool to get rid of the explicit type of the BiFunction. --- .../instantiation/BuilderInstantiator.java | 12 ++++++++++ .../BuilderInstantiatorTest.java | 23 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/main/java/com/github/nylle/javafixture/instantiation/BuilderInstantiator.java b/src/main/java/com/github/nylle/javafixture/instantiation/BuilderInstantiator.java index 111142b..3b727ab 100644 --- a/src/main/java/com/github/nylle/javafixture/instantiation/BuilderInstantiator.java +++ b/src/main/java/com/github/nylle/javafixture/instantiation/BuilderInstantiator.java @@ -8,8 +8,11 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Optional; +import java.util.function.BiFunction; import java.util.stream.Stream; import static java.util.stream.Collectors.toList; @@ -30,6 +33,13 @@ public static BuilderInstantiator create(Method builderMethodCandidate, S .orElse(null); } + private Map presetValues = new HashMap<>(); + + public BuilderInstantiator with(BiFunction setter, Object value) { + presetValues.put(setter, value); + return this; + } + public T invoke(SpecimenFactory specimenFactory, CustomizationContext customizationContext) { try { var builder = builderMethod.invoke(null, new Object[]{}); @@ -41,6 +51,8 @@ public T invoke(SpecimenFactory specimenFactory, CustomizationContext customizat .create(customizationContext, new Annotation[0]) }); } + // since we are using lambdas, the method name is not available here anymore + presetValues.entrySet().forEach(e -> e.getKey().apply(builder, e.getValue())); return (T) buildMethod.invoke(builder, new Object[]{}); } catch (InvocationTargetException | IllegalAccessException ex) { diff --git a/src/test/java/com/github/nylle/javafixture/instantiation/BuilderInstantiatorTest.java b/src/test/java/com/github/nylle/javafixture/instantiation/BuilderInstantiatorTest.java index 5472fa3..07d9216 100644 --- a/src/test/java/com/github/nylle/javafixture/instantiation/BuilderInstantiatorTest.java +++ b/src/test/java/com/github/nylle/javafixture/instantiation/BuilderInstantiatorTest.java @@ -8,6 +8,8 @@ import com.github.nylle.javafixture.testobjects.ClassWithBuilder; import org.junit.jupiter.api.Test; +import java.util.function.BiFunction; + import static org.assertj.core.api.Assertions.assertThat; class BuilderInstantiatorTest { @@ -26,4 +28,25 @@ void invokeReturnsBuiltObjectWithAllMethodsCalled() throws NoSuchMethodException assertThat(actual.getString()).isNotNull(); } + @Test + void builderCanBeCnfigured() throws NoSuchMethodException { + var sut = BuilderInstantiator.create(ClassWithBuilder.class.getMethod("builder"), SpecimenType.fromClass(ClassWithBuilder.class)); + + // we seem to need to explicitly cast it like this. + BiFunction setter = ClassWithBuilder.Builder::number; + BiFunction without = ClassWithBuilder.Builder::string; + var result = sut + .with(setter, 2) + .with(without, null) // we have lambdas, i.e. no method names, so no without + .invoke(new SpecimenFactory(new Context(new Configuration())), CustomizationContext.noContext()); + + assertThat(result).isInstanceOf(ClassWithBuilder.class); + + + var actual = (ClassWithBuilder) result; + + assertThat(actual.getNumber()).isEqualTo(2); + assertThat(actual.getString()).isNull(); + } + } From 47f3045f465396dd40beb6dac3ba3d59ea0d7ca1 Mon Sep 17 00:00:00 2001 From: Andreas Kutschera Date: Sun, 15 Sep 2024 18:03:02 +0200 Subject: [PATCH 2/2] refactor: use method reference without cast --- .../javafixture/instantiation/BuilderInstantiator.java | 2 +- .../instantiation/BuilderInstantiatorTest.java | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/github/nylle/javafixture/instantiation/BuilderInstantiator.java b/src/main/java/com/github/nylle/javafixture/instantiation/BuilderInstantiator.java index 3b727ab..c1f811a 100644 --- a/src/main/java/com/github/nylle/javafixture/instantiation/BuilderInstantiator.java +++ b/src/main/java/com/github/nylle/javafixture/instantiation/BuilderInstantiator.java @@ -35,7 +35,7 @@ public static BuilderInstantiator create(Method builderMethodCandidate, S private Map presetValues = new HashMap<>(); - public BuilderInstantiator with(BiFunction setter, Object value) { + public BuilderInstantiator with(BiFunction setter, V value) { presetValues.put(setter, value); return this; } diff --git a/src/test/java/com/github/nylle/javafixture/instantiation/BuilderInstantiatorTest.java b/src/test/java/com/github/nylle/javafixture/instantiation/BuilderInstantiatorTest.java index 07d9216..d87d822 100644 --- a/src/test/java/com/github/nylle/javafixture/instantiation/BuilderInstantiatorTest.java +++ b/src/test/java/com/github/nylle/javafixture/instantiation/BuilderInstantiatorTest.java @@ -8,8 +8,6 @@ import com.github.nylle.javafixture.testobjects.ClassWithBuilder; import org.junit.jupiter.api.Test; -import java.util.function.BiFunction; - import static org.assertj.core.api.Assertions.assertThat; class BuilderInstantiatorTest { @@ -33,11 +31,9 @@ void builderCanBeCnfigured() throws NoSuchMethodException { var sut = BuilderInstantiator.create(ClassWithBuilder.class.getMethod("builder"), SpecimenType.fromClass(ClassWithBuilder.class)); // we seem to need to explicitly cast it like this. - BiFunction setter = ClassWithBuilder.Builder::number; - BiFunction without = ClassWithBuilder.Builder::string; var result = sut - .with(setter, 2) - .with(without, null) // we have lambdas, i.e. no method names, so no without + .with(ClassWithBuilder.Builder::number, 2) + .with(ClassWithBuilder.Builder::string, null) // we have lambdas, i.e. no method names, so no without .invoke(new SpecimenFactory(new Context(new Configuration())), CustomizationContext.noContext()); assertThat(result).isInstanceOf(ClassWithBuilder.class);