Skip to content

Commit c0c6c18

Browse files
committed
refactor: Catch InaccessibleObjectException early
Any exception happening during reflection should be caught by the Reflector class and turned into a SpecimenException that we can potentially handle somewhere else in the call stack. This allows us to keep responsibilities a little closer to where they should be.
1 parent 8659bab commit c0c6c18

File tree

5 files changed

+55
-6
lines changed

5 files changed

+55
-6
lines changed

pom.xml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
<maven-gpg-plugin.version>1.5</maven-gpg-plugin.version>
2525
<nexus-staging-maven-plugin.version>1.6.8</nexus-staging-maven-plugin.version>
2626
<junit-jupiter-engine.version>5.5.1</junit-jupiter-engine.version>
27+
<mockito.version>4.5.1</mockito.version>
2728
</properties>
2829

2930
<dependencies>
@@ -70,7 +71,13 @@
7071
<dependency>
7172
<groupId>org.mockito</groupId>
7273
<artifactId>mockito-core</artifactId>
73-
<version>3.0.0</version>
74+
<version>${mockito.version}</version>
75+
<scope>test</scope>
76+
</dependency>
77+
<dependency>
78+
<groupId>org.mockito</groupId>
79+
<artifactId>mockito-inline</artifactId>
80+
<version>${mockito.version}</version>
7481
<scope>test</scope>
7582
</dependency>
7683
<dependency>

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

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

33
import java.lang.reflect.Field;
4+
import java.lang.reflect.InaccessibleObjectException;
45
import java.lang.reflect.Modifier;
56
import java.util.Optional;
67
import java.util.stream.Stream;
@@ -63,7 +64,7 @@ public void setField(Field field, Object value) {
6364
field.set(instance, value);
6465
} catch (SecurityException e) {
6566
throw new SpecimenException(format("Unable to access field %s on object of type %s", field.getName(), instance.getClass().getName()), e);
66-
} catch (IllegalAccessException e) {
67+
} catch (IllegalAccessException | InaccessibleObjectException e) {
6768
throw new SpecimenException(format("Unable to set field %s on object of type %s", field.getName(), instance.getClass().getName()), e);
6869
}
6970
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
import com.github.nylle.javafixture.ISpecimen;
66
import com.github.nylle.javafixture.InstanceFactory;
77
import com.github.nylle.javafixture.Reflector;
8+
import com.github.nylle.javafixture.SpecimenException;
89
import com.github.nylle.javafixture.SpecimenFactory;
910
import com.github.nylle.javafixture.SpecimenType;
1011

1112
import java.lang.annotation.Annotation;
12-
import java.lang.reflect.InaccessibleObjectException;
1313
import java.util.Map;
1414
import java.util.stream.IntStream;
1515

@@ -97,7 +97,7 @@ private T populate(CustomizationContext customizationContext) {
9797
specimens.getOrDefault(
9898
field.getGenericType().getTypeName(),
9999
specimenFactory.build(SpecimenType.fromClass(field.getType()))).create(new Annotation[0]))));
100-
} catch (InaccessibleObjectException ex ) {
100+
} catch (SpecimenException ex ) {
101101
return context.overwrite(type, instanceFactory.construct(type));
102102
}
103103
return result;

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
import com.github.nylle.javafixture.ISpecimen;
66
import com.github.nylle.javafixture.InstanceFactory;
77
import com.github.nylle.javafixture.Reflector;
8+
import com.github.nylle.javafixture.SpecimenException;
89
import com.github.nylle.javafixture.SpecimenFactory;
910
import com.github.nylle.javafixture.SpecimenType;
1011

1112
import java.lang.annotation.Annotation;
12-
import java.lang.reflect.InaccessibleObjectException;
1313
import java.util.Map;
1414

1515
import static com.github.nylle.javafixture.CustomizationContext.noContext;
@@ -76,7 +76,7 @@ private T populate(CustomizationContext customizationContext) {
7676
Map.<String, ISpecimen<?>>of().getOrDefault(
7777
field.getGenericType().getTypeName(),
7878
specimenFactory.build(SpecimenType.fromClass(field.getGenericType()))).create(field.getAnnotations()))));
79-
} catch (InaccessibleObjectException ex ) {
79+
} catch (SpecimenException ex ) {
8080
return context.overwrite(type, instanceFactory.construct(type));
8181
}
8282
return result;

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

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,17 @@
44
import org.junit.jupiter.api.DisplayName;
55
import org.junit.jupiter.api.Nested;
66
import org.junit.jupiter.api.Test;
7+
import org.mockito.Mockito;
78

9+
import java.lang.reflect.Field;
10+
import java.lang.reflect.InaccessibleObjectException;
811
import java.util.List;
912
import java.util.Map;
1013

1114
import static org.assertj.core.api.Assertions.assertThatCode;
1215
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
16+
import static org.mockito.ArgumentMatchers.any;
17+
import static org.mockito.Mockito.doThrow;
1318

1419
class ReflectorTest {
1520

@@ -79,4 +84,40 @@ void omittingDuplicateFields() {
7984
.withNoCause();
8085
}
8186
}
87+
88+
@Nested
89+
@DisplayName("when setting a field via reflection")
90+
class SetField {
91+
@DisplayName("an IllegalAccessException is turned to a SpecimenException")
92+
@Test
93+
void catchIllegalAccessException() throws Exception {
94+
var mockedField = Mockito.mock(Field.class);
95+
var sut = new Reflector<>("");
96+
doThrow(new IllegalAccessException("expected")).when(mockedField).set(any(), any());
97+
98+
assertThatExceptionOfType(SpecimenException.class)
99+
.isThrownBy(() -> sut.setField(mockedField, ""));
100+
}
101+
102+
@DisplayName("an IllegalAccessException is turned to a SpecimenException")
103+
@Test
104+
void catchSecurityException() {
105+
var mockedField = Mockito.mock(Field.class);
106+
var sut = new Reflector<>("");
107+
doThrow(new SecurityException("expected")).when(mockedField).setAccessible(true);
108+
assertThatExceptionOfType(SpecimenException.class)
109+
.isThrownBy(() -> sut.setField(mockedField, ""));
110+
}
111+
112+
@DisplayName("an InaccessibleObjectException is turned to a SpecimenException")
113+
@Test
114+
void catchInaccessibleObjectException() {
115+
var mockedField = Mockito.mock(Field.class);
116+
var sut = new Reflector<>("");
117+
doThrow(new InaccessibleObjectException("expected")).when(mockedField).setAccessible(true);
118+
assertThatExceptionOfType(SpecimenException.class)
119+
.isThrownBy(() -> sut.setField(mockedField, ""));
120+
}
121+
}
122+
82123
}

0 commit comments

Comments
 (0)