Skip to content

Commit fa47c4f

Browse files
committed
feat: Use factory method when constructor fails
When a constructor throws an exception we will try a factory method instead of directly failing. Only if no factory method exists will the call fail. Refs: JF-63
1 parent 7332671 commit fa47c4f

File tree

3 files changed

+42
-3
lines changed

3 files changed

+42
-3
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public <T> T construct(final SpecimenType<T> type) {
5656
.collect(toList());
5757

5858
if (constructors.isEmpty()) {
59-
throw new SpecimenException(format("Cannot construct %s: no public constructor found", type.asClass()));
59+
return manufacture(type);
6060
}
6161

6262
return construct(type, constructors.get(random.nextInt(constructors.size())));
@@ -113,7 +113,7 @@ private <T> T construct(final SpecimenType<T> type, final Constructor<?> constru
113113
.map(s -> s.create(new Annotation[0]))
114114
.toArray());
115115
} catch (Exception e) {
116-
throw new SpecimenException(format("Unable to construct class %s with constructor %s: %s", type.asClass(), constructor.toString(), e.getMessage()), e);
116+
return manufacture(type);
117117
}
118118
}
119119

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

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.github.nylle.javafixture;
22

33
import com.github.nylle.javafixture.testobjects.TestObjectWithGenericConstructor;
4+
import com.github.nylle.javafixture.testobjects.factorymethod.ConstructorExceptionAndFactoryMethod;
45
import com.github.nylle.javafixture.testobjects.factorymethod.TestObjectWithNonPublicFactoryMethods;
56
import com.github.nylle.javafixture.testobjects.TestObjectWithPrivateConstructor;
67
import com.github.nylle.javafixture.testobjects.factorymethod.FactoryMethodWithArgument;
@@ -67,7 +68,7 @@ void canOnlyUsePublicConstructor() {
6768

6869
assertThatExceptionOfType(SpecimenException.class)
6970
.isThrownBy(() -> sut.construct(fromClass(TestObjectWithPrivateConstructor.class)))
70-
.withMessageContaining("no public constructor found")
71+
.withMessageContaining("Cannot manufacture class")
7172
.withNoCause();
7273
}
7374

@@ -80,6 +81,24 @@ void canCreateInstanceFromAbstractClassUsingFactoryMethod() {
8081
assertThat(actual).isInstanceOf(Charset.class);
8182
}
8283

84+
@Test
85+
void useFactoryMethodWhenNoConstructorExists() {
86+
var sut = new InstanceFactory(new SpecimenFactory(new Context(Configuration.configure())));
87+
88+
FactoryMethodWithoutArgument result = sut.construct(fromClass(FactoryMethodWithoutArgument.class));
89+
90+
assertThat(result.getValue()).isEqualTo(42);
91+
}
92+
93+
@Test
94+
void fallbackToFactoryMethodWhenConstructorThrowsException() {
95+
var sut = new InstanceFactory(new SpecimenFactory(new Context(Configuration.configure())));
96+
97+
ConstructorExceptionAndFactoryMethod result = sut.construct(new SpecimenType<ConstructorExceptionAndFactoryMethod>() {});
98+
99+
assertThat(result.getValue()).isNotNull();
100+
}
101+
83102
@Nested
84103
@DisplayName("when manufacturing using factory methods")
85104
class FactoryMethods {
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.github.nylle.javafixture.testobjects.factorymethod;
2+
3+
public class ConstructorExceptionAndFactoryMethod {
4+
private int value;
5+
6+
public ConstructorExceptionAndFactoryMethod() {
7+
throw new IllegalArgumentException("expected for tests");
8+
}
9+
private ConstructorExceptionAndFactoryMethod(int value) {
10+
this.value = value;
11+
}
12+
13+
public static ConstructorExceptionAndFactoryMethod factoryMethod() {
14+
return new ConstructorExceptionAndFactoryMethod(42);
15+
}
16+
17+
public int getValue() {
18+
return value;
19+
}
20+
}

0 commit comments

Comments
 (0)