Skip to content

Commit 6cb8947

Browse files
committed
feat: provide builder-wrapper
1 parent 2e1ab77 commit 6cb8947

File tree

3 files changed

+125
-0
lines changed

3 files changed

+125
-0
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package com.github.nylle.javafixture;
2+
3+
import java.lang.annotation.Annotation;
4+
import java.lang.reflect.InvocationTargetException;
5+
import java.lang.reflect.Method;
6+
import java.lang.reflect.Modifier;
7+
import java.util.List;
8+
import java.util.Optional;
9+
import java.util.stream.Stream;
10+
11+
import static java.util.stream.Collectors.toList;
12+
13+
public class Builder<T> {
14+
15+
private final Method buildMethod;
16+
private final Method builderMethod;
17+
18+
private Builder(Method builderMethod, Method buildMethod) {
19+
this.builderMethod = builderMethod;
20+
this.buildMethod = buildMethod;
21+
}
22+
23+
public static <T> Builder<T> create(Method builderMethodCandidate, SpecimenType<T> targetType) {
24+
return findBuildMethod(builderMethodCandidate.getReturnType(), targetType.asClass())
25+
.map(x -> new Builder<T>(builderMethodCandidate, x))
26+
.orElse(null);
27+
}
28+
29+
public T invoke(SpecimenFactory specimenFactory, CustomizationContext customizationContext) {
30+
try {
31+
var builder = builderMethod.invoke(null, new Object[]{});
32+
33+
for (var method : findSetMethods()) {
34+
method.invoke(builder, new Object[]{specimenFactory.build(SpecimenType.fromClass(method.getGenericParameterTypes()[0])).create(customizationContext, new Annotation[0])});
35+
}
36+
37+
return (T) buildMethod.invoke(builder, new Object[]{});
38+
} catch (InvocationTargetException | IllegalAccessException ex) {
39+
return null;
40+
}
41+
}
42+
43+
private List<Method> findSetMethods() {
44+
return Stream.of(builderMethod.getReturnType().getDeclaredMethods())
45+
.filter(x -> !Modifier.isStatic(x.getModifiers()))
46+
.filter(x -> Modifier.isPublic(x.getModifiers()))
47+
.filter(x -> x.getParameterCount() == 1)
48+
.collect(toList());
49+
}
50+
51+
private static <T> Optional<Method> findBuildMethod(Class<?> builderClass, Class<T> targetType) {
52+
return Stream.of(builderClass.getDeclaredMethods())
53+
.filter(x -> !Modifier.isStatic(x.getModifiers()))
54+
.filter(x -> Modifier.isPublic(x.getModifiers()))
55+
.filter(x -> x.getReturnType().equals(targetType))
56+
.filter(x -> x.getParameterCount() == 0)
57+
.findFirst();
58+
}
59+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.github.nylle.javafixture;
2+
3+
import com.github.nylle.javafixture.testobjects.ClassWithBuilder;
4+
import org.junit.jupiter.api.Test;
5+
6+
import static org.assertj.core.api.Assertions.assertThat;
7+
8+
class BuilderTest {
9+
10+
@Test
11+
void invokeReturnsBuiltObjectWithAllMethodsCalled() throws NoSuchMethodException {
12+
var sut = Builder.create(ClassWithBuilder.class.getMethod("builder"), SpecimenType.fromClass(ClassWithBuilder.class));
13+
14+
var result = sut.invoke(new SpecimenFactory(new Context(new Configuration())), CustomizationContext.noContext());
15+
16+
assertThat(result).isInstanceOf(ClassWithBuilder.class);
17+
18+
var actual = (ClassWithBuilder) result;
19+
20+
assertThat(actual.getNumber()).isNotNull();
21+
assertThat(actual.getString()).isNotNull();
22+
}
23+
24+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.github.nylle.javafixture.testobjects;
2+
3+
public class ClassWithBuilder {
4+
private final String string;
5+
private final Integer number;
6+
7+
private ClassWithBuilder(String string, Integer number) {
8+
this.string = string;
9+
this.number = number;
10+
}
11+
12+
public static Builder builder() {
13+
return new Builder();
14+
}
15+
16+
public String getString() {
17+
return string;
18+
}
19+
20+
public Integer getNumber() {
21+
return number;
22+
}
23+
24+
public static class Builder {
25+
private String string;
26+
private Integer number;
27+
28+
public Builder string(String string) {
29+
this.string = string;
30+
return this;
31+
}
32+
33+
public Builder number(Integer number) {
34+
this.number = number;
35+
return this;
36+
}
37+
38+
public ClassWithBuilder build() {
39+
return new ClassWithBuilder(string, number);
40+
}
41+
}
42+
}

0 commit comments

Comments
 (0)