Skip to content

Commit 93782e5

Browse files
committed
feat: Use constructor when reflection fails
Refs: JF-63
1 parent fa47c4f commit 93782e5

File tree

6 files changed

+53
-32
lines changed

6 files changed

+53
-32
lines changed

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ public boolean isCached(SpecimenType<?> type) {
3535
return cache.containsKey(type.hashCode());
3636
}
3737

38+
public <T> T overwrite(SpecimenType<?> type, T instance) {
39+
cache.put(type.hashCode(), instance);
40+
return (T) cache.get(type.hashCode());
41+
}
42+
3843
public <T> T cached(SpecimenType<?> type, T instance) {
3944
cache.putIfAbsent(type.hashCode(), instance);
4045
return (T) cache.get(type.hashCode());

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

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.github.nylle.javafixture.SpecimenType;
1010

1111
import java.lang.annotation.Annotation;
12+
import java.lang.reflect.InaccessibleObjectException;
1213
import java.util.Map;
1314
import java.util.stream.IntStream;
1415

@@ -87,14 +88,18 @@ private T populate(CustomizationContext customizationContext) {
8788
var result = context.cached(type, instanceFactory.instantiate(type));
8889
var reflector = new Reflector<>(result)
8990
.validateCustomization(customizationContext, type);
90-
reflector.getDeclaredFields()
91-
.filter(field -> !customizationContext.getIgnoredFields().contains(field.getName()))
92-
.forEach(field -> reflector.setField(field,
93-
customizationContext.getCustomFields().getOrDefault(
94-
field.getName(),
95-
specimens.getOrDefault(
96-
field.getGenericType().getTypeName(),
97-
specimenFactory.build(SpecimenType.fromClass(field.getType()))).create(new Annotation[0]))));
91+
try {
92+
reflector.getDeclaredFields()
93+
.filter(field -> !customizationContext.getIgnoredFields().contains(field.getName()))
94+
.forEach(field -> reflector.setField(field,
95+
customizationContext.getCustomFields().getOrDefault(
96+
field.getName(),
97+
specimens.getOrDefault(
98+
field.getGenericType().getTypeName(),
99+
specimenFactory.build(SpecimenType.fromClass(field.getType()))).create(new Annotation[0]))));
100+
} catch (InaccessibleObjectException ex ) {
101+
return context.overwrite(type, instanceFactory.construct(type));
102+
}
98103
return result;
99104
}
100105
}

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

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.github.nylle.javafixture.SpecimenType;
1010

1111
import java.lang.annotation.Annotation;
12+
import java.lang.reflect.InaccessibleObjectException;
1213
import java.util.Map;
1314

1415
import static com.github.nylle.javafixture.CustomizationContext.noContext;
@@ -66,14 +67,18 @@ private T populate(CustomizationContext customizationContext) {
6667
var result = context.cached(type, instanceFactory.instantiate(type));
6768
var reflector = new Reflector<>(result)
6869
.validateCustomization(customizationContext, type);
69-
reflector.getDeclaredFields()
70-
.filter(field -> !customizationContext.getIgnoredFields().contains(field.getName()))
71-
.forEach(field -> reflector.setField(field,
72-
customizationContext.getCustomFields().getOrDefault(
73-
field.getName(),
74-
Map.<String, ISpecimen<?>>of().getOrDefault(
75-
field.getGenericType().getTypeName(),
76-
specimenFactory.build(SpecimenType.fromClass(field.getGenericType()))).create(field.getAnnotations()))));
70+
try {
71+
reflector.getDeclaredFields()
72+
.filter(field -> !customizationContext.getIgnoredFields().contains(field.getName()))
73+
.forEach(field -> reflector.setField(field,
74+
customizationContext.getCustomFields().getOrDefault(
75+
field.getName(),
76+
Map.<String, ISpecimen<?>>of().getOrDefault(
77+
field.getGenericType().getTypeName(),
78+
specimenFactory.build(SpecimenType.fromClass(field.getGenericType()))).create(field.getAnnotations()))));
79+
} catch (InaccessibleObjectException ex ) {
80+
return context.overwrite(type, instanceFactory.construct(type));
81+
}
7782
return result;
7883
}
7984
}

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,21 @@ void cachedReturnsCachedInstanceWhenExisting() {
4141

4242
}
4343

44+
@Test
45+
void overwriteWillRemovePreviousValue() {
46+
var sut = new Context(new Configuration());
47+
48+
var unexpected = new TestObject("Hello!");
49+
sut.cached(SpecimenType.fromClass(Integer.class), unexpected);
50+
51+
var expected = new TestObject("World!");
52+
var actual = sut.overwrite(SpecimenType.fromClass(Integer.class), expected);
53+
54+
assertThat(actual).isEqualTo(expected);
55+
assertThat(actual.getValue()).isEqualTo("World!");
56+
57+
}
58+
4459
class TestObject {
4560
private final String value;
4661

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

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import com.github.nylle.javafixture.testobjects.example.Contract;
2020
import com.github.nylle.javafixture.testobjects.example.ContractCategory;
2121
import com.github.nylle.javafixture.testobjects.example.ContractPosition;
22-
import org.junit.jupiter.api.Disabled;
2322
import org.junit.jupiter.api.DisplayName;
2423
import org.junit.jupiter.api.Nested;
2524
import org.junit.jupiter.api.Test;
@@ -295,19 +294,6 @@ void canCreateComplexModel() {
295294
assertThat(firstContractPosition.getFile()).isInstanceOf(File.class);
296295
}
297296

298-
@Test
299-
void canCreateThrowable() {
300-
Fixture fixture = new Fixture(configuration);
301-
302-
Throwable result = fixture.create(Throwable.class);
303-
assertThat(result).isInstanceOf(Throwable.class);
304-
assertThat(result.getMessage().length()).isGreaterThan(0);
305-
assertThat(result.getLocalizedMessage().length()).isGreaterThan(0);
306-
assertThat(result.getStackTrace().length).isGreaterThan(0);
307-
assertThat(result.getStackTrace()[0]).isInstanceOf(StackTraceElement.class);
308-
assertThat(result.getCause()).isNull(); //if cause == this, the getter returns null
309-
}
310-
311297
@Test
312298
void canCreateNestedParameterizedCollections() {
313299
Fixture fixture = new Fixture(configuration);
@@ -596,7 +582,6 @@ void createThroughRandomConstructor() {
596582
}
597583

598584
@Test
599-
@Disabled("This is a known problem")
600585
void createExceptionWithLimitedTree() {
601586

602587
var sut = new Fixture(configuration);

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ void create() {
8686
assertThat(second.getKey()).isExactlyInstanceOf(Integer.class);
8787
assertThat(second.getValue()).isExactlyInstanceOf(String.class);
8888
}
89-
9089
@Test
9190
void resultIsCached() {
9291

@@ -98,6 +97,13 @@ void resultIsCached() {
9897
assertThat(original.getValue()).isEqualTo(cached.getValue());
9998
assertThat(original.getIntegers()).isEqualTo(cached.getIntegers());
10099
}
100+
@Test
101+
void revertToConstructorIfReflectionFails() {
102+
103+
var actual = new ObjectSpecimen<Throwable>(new SpecimenType<>(){}, context, specimenFactory).create(new Annotation[0]);
104+
105+
assertThat(actual).isInstanceOf(Throwable.class);
106+
}
101107

102108
@Test
103109
void ignoresStaticFields() {

0 commit comments

Comments
 (0)