Skip to content

Commit 9d95498

Browse files
akutscheraNylle
authored andcommitted
Refactor CustomizationContext
Now we only have one public constructor with all three fields. Also, the collections are now un-modifiable to prevent difficult-to-maintain behaviour. #Refs: #92
1 parent dd0be28 commit 9d95498

File tree

9 files changed

+36
-43
lines changed

9 files changed

+36
-43
lines changed

src/main/java/com/github/nylle/javafixture/CustomizationContext.java

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,17 @@ public class CustomizationContext {
1212

1313

1414
private CustomizationContext() {
15-
ignoredFields = Collections.emptyList();
15+
ignoredFields = List.of();
1616
customFields = new HashMap<>();
1717
useRandomConstructor = false;
1818
}
1919

20-
public CustomizationContext(final boolean useRandomConstructor) {
21-
ignoredFields = Collections.emptyList();
22-
customFields = new HashMap<>();
20+
public CustomizationContext(final List<String> ignoredFields, final Map<String, Object> customFields, boolean useRandomConstructor) {
21+
this.ignoredFields = Collections.unmodifiableList(ignoredFields);
22+
this.customFields = Collections.unmodifiableMap(customFields);
2323
this.useRandomConstructor = useRandomConstructor;
2424
}
2525

26-
public CustomizationContext(final List<String> ignoredFields, final Map<String, Object> customFields) {
27-
this.ignoredFields = ignoredFields;
28-
this.customFields = customFields;
29-
this.useRandomConstructor = false;
30-
}
31-
3226
public static CustomizationContext noContext() {
3327
return new CustomizationContext();
3428
}

src/main/java/com/github/nylle/javafixture/InstanceFactory.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,10 @@ private <T> T construct(final SpecimenType<T> type, final Constructor<?> constru
122122

123123
private Object createParameter(Parameter parameter, CustomizationContext customizationContext) {
124124
if (customizationContext.getCustomFields().containsKey(parameter.getName())) {
125-
return customizationContext.getCustomFields().remove(parameter.getName());
125+
return customizationContext.getCustomFields().get(parameter.getName());
126126
}
127127
var specimen = specimenFactory.build(SpecimenType.fromClass(parameter.getParameterizedType()));
128-
return specimen.create(customizationContext, new Annotation[0]);
128+
return specimen.create(new CustomizationContext(List.of(), Map.of(), customizationContext.useRandomConstructor()), new Annotation[0]);
129129
}
130130

131131
private <T> T createProxyForAbstract(final SpecimenType<T> type, final Map<String, ISpecimen<?>> specimens) {

src/main/java/com/github/nylle/javafixture/SpecimenBuilder.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public SpecimenBuilder(final SpecimenType<T> type, final Configuration configura
3030
*/
3131
@Override
3232
public T create() {
33-
return customize(new SpecimenFactory(new Context(configuration, predefinedInstances)).build(type).create(new CustomizationContext(ignoredFields, customFields), new Annotation[0]));
33+
return customize(new SpecimenFactory(new Context(configuration, predefinedInstances)).build(type).create(new CustomizationContext(ignoredFields, customFields, false), new Annotation[0]));
3434
}
3535

3636
/**
@@ -130,7 +130,7 @@ public ISpecimenBuilder<T> without(final String fieldName) {
130130
}
131131

132132
T construct() {
133-
return new SpecimenFactory(new Context(configuration)).build(type).create(new CustomizationContext(true), new Annotation[0]);
133+
return new SpecimenFactory(new Context(configuration)).build(type).create(new CustomizationContext(List.of(), Map.of(), true), new Annotation[0]);
134134
}
135135

136136
private T customize(T instance) {

src/main/java/com/github/nylle/javafixture/specimen/GenericSpecimen.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ private T populate(CustomizationContext customizationContext) {
9191
field.getName(),
9292
specimens.getOrDefault(
9393
field.getGenericType().getTypeName(),
94-
specimenFactory.build(SpecimenType.fromClass(field.getType()))).create(new CustomizationContext(List.of(), Map.of()), new Annotation[0]))));
94+
specimenFactory.build(SpecimenType.fromClass(field.getType()))).create(new CustomizationContext(List.of(), Map.of(), false), new Annotation[0]))));
9595
} catch (SpecimenException ex) {
9696
return context.overwrite(type, instanceFactory.construct(type, customizationContext));
9797
}

src/main/java/com/github/nylle/javafixture/specimen/ObjectSpecimen.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ private T populate(CustomizationContext customizationContext) {
6969
field.getName(),
7070
Map.<String, ISpecimen<?>>of().getOrDefault(
7171
field.getGenericType().getTypeName(),
72-
specimenFactory.build(SpecimenType.fromClass(field.getGenericType()))).create(new CustomizationContext(List.of(), Map.of()), field.getAnnotations()))));
72+
specimenFactory.build(SpecimenType.fromClass(field.getGenericType()))).create(new CustomizationContext(List.of(), Map.of(), false), field.getAnnotations()))));
7373
} catch (SpecimenException ex ) {
7474
return context.overwrite(type, instanceFactory.construct(type, customizationContext));
7575
}

src/test/java/com/github/nylle/javafixture/InstanceFactoryTest.java

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.util.HashSet;
2525
import java.util.LinkedList;
2626
import java.util.List;
27+
import java.util.Map;
2728
import java.util.NavigableSet;
2829
import java.util.Optional;
2930
import java.util.Queue;
@@ -52,7 +53,7 @@ class UsingConstructor {
5253
void canCreateInstanceFromConstructor() {
5354
var sut = new InstanceFactory(new SpecimenFactory(new Context(Configuration.configure())));
5455

55-
TestObjectWithGenericConstructor result = sut.construct(fromClass(TestObjectWithGenericConstructor.class), new CustomizationContext(false));
56+
TestObjectWithGenericConstructor result = sut.construct(fromClass(TestObjectWithGenericConstructor.class), new CustomizationContext(List.of(), Map.of(), false));
5657

5758
assertThat(result).isInstanceOf(TestObjectWithGenericConstructor.class);
5859
assertThat(result.getValue()).isInstanceOf(String.class);
@@ -65,7 +66,7 @@ void fieldsNotSetByConstructorAreNull() {
6566

6667
var sut = new InstanceFactory(new SpecimenFactory(new Context(Configuration.configure())));
6768

68-
TestObjectWithGenericConstructor result = sut.construct(fromClass(TestObjectWithGenericConstructor.class), new CustomizationContext(false));
69+
TestObjectWithGenericConstructor result = sut.construct(fromClass(TestObjectWithGenericConstructor.class), new CustomizationContext(List.of(), Map.of(), false));
6970

7071
assertThat(result).isInstanceOf(TestObjectWithGenericConstructor.class);
7172
assertThat(result.getPrivateField()).isNull();
@@ -77,7 +78,7 @@ void usingConstructorIsRecursive() {
7778

7879
var sut = new InstanceFactory(new SpecimenFactory(new Context(Configuration.configure())));
7980

80-
TestObjectWithConstructedField result = sut.construct(fromClass(TestObjectWithConstructedField.class), new CustomizationContext(true));
81+
TestObjectWithConstructedField result = sut.construct(fromClass(TestObjectWithConstructedField.class), new CustomizationContext(List.of(), Map.of(), true));
8182

8283
assertThat(result).isInstanceOf(TestObjectWithConstructedField.class);
8384
assertThat(result.getTestObjectWithGenericConstructor().getPrivateField()).isNull();
@@ -90,7 +91,7 @@ void canOnlyUsePublicConstructor() {
9091
var sut = new InstanceFactory(new SpecimenFactory(new Context(Configuration.configure())));
9192

9293
assertThatExceptionOfType(SpecimenException.class)
93-
.isThrownBy(() -> sut.construct(fromClass(TestObjectWithPrivateConstructor.class), new CustomizationContext(false)))
94+
.isThrownBy(() -> sut.construct(fromClass(TestObjectWithPrivateConstructor.class), new CustomizationContext(List.of(), Map.of(), false)))
9495
.withMessageContaining("Cannot manufacture class")
9596
.withNoCause();
9697
}
@@ -100,7 +101,7 @@ void canOnlyUsePublicConstructor() {
100101
void useFactoryMethodWhenNoConstructorExists() {
101102
var sut = new InstanceFactory(new SpecimenFactory(new Context(Configuration.configure())));
102103

103-
FactoryMethodWithoutArgument result = sut.construct(fromClass(FactoryMethodWithoutArgument.class), new CustomizationContext(false));
104+
FactoryMethodWithoutArgument result = sut.construct(fromClass(FactoryMethodWithoutArgument.class), new CustomizationContext(List.of(), Map.of(), false));
104105

105106
assertThat(result.getValue()).isEqualTo(42);
106107
}
@@ -110,7 +111,7 @@ void useFactoryMethodWhenNoConstructorExists() {
110111
void fallbackToFactoryMethodWhenConstructorThrowsException() {
111112
var sut = new InstanceFactory(new SpecimenFactory(new Context(Configuration.configure())));
112113

113-
var result = sut.construct(new SpecimenType<ConstructorExceptionAndFactoryMethod>() {}, new CustomizationContext(false));
114+
var result = sut.construct(new SpecimenType<ConstructorExceptionAndFactoryMethod>() {}, new CustomizationContext(List.of(), Map.of(), false));
114115

115116
assertThat(result.getValue()).isNotNull();
116117
}
@@ -120,9 +121,8 @@ void fallbackToFactoryMethodWhenConstructorThrowsException() {
120121
void argumentsCanBeCustomized() {
121122
var sut = new InstanceFactory(new SpecimenFactory(new Context(Configuration.configure())));
122123

123-
var customizationContext = new CustomizationContext(true);
124124
// use arg0, because .class files do not store formal parameter names by default
125-
customizationContext.getCustomFields().put("arg0", "customized");
125+
var customizationContext = new CustomizationContext(List.of(), Map.of("arg0", "customized"), true);
126126
TestObject result = sut.construct(fromClass(TestObject.class), customizationContext);
127127

128128
assertThat(result.getValue()).isEqualTo("customized");
@@ -133,7 +133,7 @@ void argumentsCanBeCustomized() {
133133
void constructorArgumentsAreCached() {
134134
var sut = new InstanceFactory(new SpecimenFactory(new Context(Configuration.configure())));
135135

136-
var customizationContext = new CustomizationContext(true);
136+
var customizationContext = new CustomizationContext(List.of(), Map.of(), true);
137137
TestObject first = sut.construct(fromClass(TestObject.class), customizationContext);
138138
TestObject second = sut.construct(fromClass(TestObject.class), customizationContext);
139139

@@ -147,8 +147,7 @@ void constructorArgumentsAreCached() {
147147
void constructorArgumentsAreUsedOnce() {
148148
var sut = new InstanceFactory(new SpecimenFactory(new Context(Configuration.configure())));
149149

150-
var customizationContext = new CustomizationContext(true);
151-
customizationContext.getCustomFields().put("arg0", 2);
150+
var customizationContext = new CustomizationContext(List.of(), Map.of("arg0", 2), true);
152151
TestObjectWithConstructedField result = sut.construct(fromClass(TestObjectWithConstructedField.class), customizationContext);
153152

154153
assertThat(result.getSetByConstructor()).isEqualTo(2);

src/test/java/com/github/nylle/javafixture/ReflectorTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ void validCustomization() {
2828

2929
var sut = new Reflector<>(new GenericChild<String>());
3030

31-
var validCustomisation = new CustomizationContext(List.of(), Map.of("baseField", "foo"));
31+
var validCustomisation = new CustomizationContext(List.of(), Map.of("baseField", "foo"), false);
3232

3333
assertThatCode(() -> sut.validateCustomization(validCustomisation, new SpecimenType<>() {}))
3434
.doesNotThrowAnyException();
@@ -40,7 +40,7 @@ void invalidCustomization() {
4040

4141
var sut = new Reflector<>(new GenericChild<String>());
4242

43-
var invalidCustomisation = new CustomizationContext(List.of(), Map.of("nonExistingField", "foo"));
43+
var invalidCustomisation = new CustomizationContext(List.of(), Map.of("nonExistingField", "foo"), false);
4444

4545
assertThatExceptionOfType(SpecimenException.class)
4646
.isThrownBy(() -> sut.validateCustomization(invalidCustomisation, new SpecimenType<>() {}))
@@ -56,7 +56,7 @@ void customizingDuplicateFields() {
5656

5757
Map<String, Object> customization = Map.of("fieldIn2Classes", 100.0);
5858

59-
var invalidCustomisation = new CustomizationContext(List.of(), customization);
59+
var invalidCustomisation = new CustomizationContext(List.of(), customization, false);
6060

6161
assertThatExceptionOfType(SpecimenException.class)
6262
.isThrownBy(() -> sut.validateCustomization(invalidCustomisation, new SpecimenType<>() {}))
@@ -74,7 +74,7 @@ void omittingDuplicateFields() {
7474

7575
var omitting = List.of("fieldIn2Classes");
7676

77-
var invalidCustomisation = new CustomizationContext(omitting, Map.of());
77+
var invalidCustomisation = new CustomizationContext(omitting, Map.of(), false);
7878

7979
assertThatExceptionOfType(SpecimenException.class)
8080
.isThrownBy(() -> sut.validateCustomization(invalidCustomisation, new SpecimenType<>() {}))

src/test/java/com/github/nylle/javafixture/specimen/GenericSpecimenTest.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ void subSpecimenAreProperlyCached() {
112112
void cannotSetNonExistingField() {
113113
var sut = new GenericSpecimen<>(new SpecimenType<TestObjectGeneric<String, Integer>>() {}, context, specimenFactory);
114114

115-
var customizationContext = new CustomizationContext(List.of(), Map.of("nonExistingField", "foo"));
115+
var customizationContext = new CustomizationContext(List.of(), Map.of("nonExistingField", "foo"), false);
116116

117117
assertThatExceptionOfType(Exception.class)
118118
.isThrownBy(() -> sut.create(customizationContext, new Annotation[0]))
@@ -124,7 +124,7 @@ void cannotSetNonExistingField() {
124124
void cannotOmitNonExistingField() {
125125
var sut = new GenericSpecimen<>(new SpecimenType<TestObjectGeneric<String, Integer>>() {}, context, specimenFactory);
126126

127-
var customizationContext = new CustomizationContext(List.of("nonExistingField"), Map.of());
127+
var customizationContext = new CustomizationContext(List.of("nonExistingField"), Map.of(), false);
128128

129129
assertThatExceptionOfType(Exception.class)
130130
.isThrownBy(() -> sut.create(customizationContext, new Annotation[0]))
@@ -136,7 +136,7 @@ void cannotOmitNonExistingField() {
136136
void customFieldIsOnlyUsedInTopLevelObject() {
137137
var sut = new GenericSpecimen<>(new SpecimenType<WithTestObject<Integer>>() {}, context, specimenFactory);
138138

139-
var customizationContext = new CustomizationContext(List.of(), Map.of("topLevelValue", 42));
139+
var customizationContext = new CustomizationContext(List.of(), Map.of("topLevelValue", 42), false);
140140

141141
var actual = sut.create(customizationContext, new Annotation[0]);
142142

@@ -178,7 +178,7 @@ void subClassFieldsAreCustomizable() {
178178
"parentField", "bar",
179179
"baseField", "baz");
180180

181-
var actual = sut.create(new CustomizationContext(List.of(), customization), new Annotation[0]);
181+
var actual = sut.create(new CustomizationContext(List.of(), customization, false), new Annotation[0]);
182182

183183
assertThat(actual.getChildField()).isEqualTo("foo");
184184
assertThat(actual.getParentField()).isEqualTo("bar");
@@ -200,7 +200,7 @@ void firstFieldPerNameIsCustomized() {
200200
"fieldIn2Classes", 100.0);
201201

202202
assertThatExceptionOfType(SpecimenException.class)
203-
.isThrownBy(() -> sut.create(new CustomizationContext(List.of(), customization), new Annotation[0]));
203+
.isThrownBy(() -> sut.create(new CustomizationContext(List.of(), customization, false), new Annotation[0]));
204204
}
205205

206206
@Test
@@ -213,7 +213,7 @@ void firstFieldPerNameIsOmitted() {
213213
"fieldIn2Classes");
214214

215215
assertThatExceptionOfType(SpecimenException.class)
216-
.isThrownBy(() -> sut.create(new CustomizationContext(omitting, Map.of()), new Annotation[0]));
216+
.isThrownBy(() -> sut.create(new CustomizationContext(omitting, Map.of(), false), new Annotation[0]));
217217
}
218218
}
219219

src/test/java/com/github/nylle/javafixture/specimen/ObjectSpecimenTest.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ void ignoresStaticFields() {
118118
void cannotSetNonExistingField() {
119119
var sut = new ObjectSpecimen<TestObject>(SpecimenType.fromClass(TestObject.class), context, specimenFactory);
120120

121-
var customizationContext = new CustomizationContext(List.of(), Map.of("nonExistingField", "foo"));
121+
var customizationContext = new CustomizationContext(List.of(), Map.of("nonExistingField", "foo"), false);
122122

123123
assertThatExceptionOfType(Exception.class)
124124
.isThrownBy(() -> sut.create(customizationContext, new Annotation[0]))
@@ -130,7 +130,7 @@ void cannotSetNonExistingField() {
130130
void cannotOmitNonExistingField() {
131131
var sut = new ObjectSpecimen<TestObject>(SpecimenType.fromClass(TestObject.class), context, specimenFactory);
132132

133-
var customizationContext = new CustomizationContext(List.of("nonExistingField"), Map.of());
133+
var customizationContext = new CustomizationContext(List.of("nonExistingField"), Map.of(), false);
134134

135135
assertThatExceptionOfType(Exception.class)
136136
.isThrownBy(() -> sut.create(customizationContext, new Annotation[0]))
@@ -141,7 +141,7 @@ void cannotOmitNonExistingField() {
141141
@Test
142142
void customFieldIsOnlyUsedInTopLevelObject() {
143143
var sut = new ObjectSpecimen<WithTestObject>(SpecimenType.fromClass(WithTestObject.class), context, specimenFactory);
144-
var customizationContext = new CustomizationContext(List.of(), Map.of("topLevelValue", 42));
144+
var customizationContext = new CustomizationContext(List.of(), Map.of("topLevelValue", 42), false);
145145
var actual = sut.create(customizationContext, new Annotation[0]);
146146
assertThat(actual.getTopLevelValue()).isEqualTo(42);
147147
assertThat( actual.getTestObject() ).isNotNull();
@@ -181,7 +181,7 @@ void subClassFieldsAreCustomizable() {
181181
"parentField", "bar",
182182
"baseField", "baz");
183183

184-
var actual = sut.create(new CustomizationContext(List.of(), customization), new Annotation[0]);
184+
var actual = sut.create(new CustomizationContext(List.of(), customization, false), new Annotation[0]);
185185

186186
assertThat(actual.getChildField()).isEqualTo("foo");
187187
assertThat(actual.getParentField()).isEqualTo("bar");
@@ -203,7 +203,7 @@ void firstFieldPerNameIsCustomized() {
203203
"fieldIn2Classes", 100.0);
204204

205205
assertThatExceptionOfType(SpecimenException.class)
206-
.isThrownBy(() -> sut.create(new CustomizationContext(List.of(), customization), new Annotation[0]));
206+
.isThrownBy(() -> sut.create(new CustomizationContext(List.of(), customization, false), new Annotation[0]));
207207
}
208208

209209
@Test
@@ -216,7 +216,7 @@ void firstFieldPerNameIsOmitted() {
216216
"fieldIn2Classes");
217217

218218
assertThatExceptionOfType(SpecimenException.class)
219-
.isThrownBy(() -> sut.create(new CustomizationContext(omitting, Map.of()), new Annotation[0]));
219+
.isThrownBy(() -> sut.create(new CustomizationContext(omitting, Map.of(), false), new Annotation[0]));
220220
}
221221
}
222222

0 commit comments

Comments
 (0)