Skip to content

Commit 56211f9

Browse files
authored
Merge pull request #107 from ocadotechnology/67-overriding-in-records
test-arranger-67: overriding primitives in records
2 parents 2bc2339 + 10e4802 commit 56211f9

8 files changed

Lines changed: 159 additions & 15 deletions

File tree

src/main/java/com/ocadotechnology/gembus/test/Arranger.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,9 @@ public static <T> T some(final Class<T> type, final String... excludedFields) {
6060
*/
6161
public static <T> T some(final Class<T> type, final Map<String, Supplier<?>> overrides) {
6262
CurrentEnhancedRandom.set(random);
63-
String[] toIgnore = overrides.keySet().toArray(new String[overrides.size()]);
63+
String[] toIgnore = overrides.keySet().stream()
64+
.filter(field -> !ReflectionHelper.isPrimitiveField(type, field))
65+
.toArray(String[]::new);
6466
T result = random.nextObject(type, toIgnore);
6567
if (type.isRecord()) {
6668
return Rearranger.copy(result, overrides);

src/main/java/com/ocadotechnology/gembus/test/ReflectionHelper.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import io.github.classgraph.ClassGraph;
1919

2020
import java.lang.reflect.Constructor;
21+
import java.lang.reflect.Field;
2122
import java.lang.reflect.Modifier;
2223
import java.util.Arrays;
2324
import java.util.List;
@@ -47,6 +48,22 @@ class ReflectionHelper {
4748
.collect(Collectors.toList());
4849
}
4950

51+
static boolean isPrimitiveField(Class<?> clazz, String fieldName) {
52+
if (fieldName == null || fieldName.isEmpty()) {
53+
return false;
54+
}
55+
Class<?> current = clazz;
56+
while (current != null) {
57+
try {
58+
Field field = current.getDeclaredField(fieldName);
59+
return field.getType().isPrimitive();
60+
} catch (NoSuchFieldException e) {
61+
current = current.getSuperclass();
62+
}
63+
}
64+
return false;
65+
}
66+
5067
Map<Class<?>, CustomArranger<?>> createAllCustomArrangers() {
5168
return customArrangers = arrangerConstructors.stream()
5269
.map(constructor -> createCustomArranger(constructor))

src/test/java/com/ocadotechnology/gembus/test/ArrangerTestEnumSet.java renamed to src/test/java/com/ocadotechnology/gembus/test/ArrangerEnumSetTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
import static com.ocadotechnology.gembus.test.Arranger.someObjects;
3030
import static org.assertj.core.api.Assertions.assertThat;
3131

32-
public class ArrangerTestEnumSet {
32+
public class ArrangerEnumSetTest {
3333

3434
@Test
3535
@DisplayName("SHOULD not try to initialize file WHEN an override is delivered")

src/test/java/com/ocadotechnology/gembus/test/ArrangerTestNestedObjects.java renamed to src/test/java/com/ocadotechnology/gembus/test/ArrangerNestedObjectsTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
import static org.assertj.core.api.Assertions.assertThat;
2727
import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively;
2828

29-
public class ArrangerTestNestedObjects {
29+
public class ArrangerNestedObjectsTest {
3030

3131
static final String FIXED_TEXT = "text";
3232

@@ -127,7 +127,7 @@ class NestedStructureArranger extends CustomArranger<NestedStructure> {
127127
@Override
128128
protected NestedStructure instance() {
129129
NestedStructure nestedStructure = enhancedRandom.nextObject(NestedStructure.class, "dummyId");
130-
nestedStructure.text = ArrangerTestNestedObjects.FIXED_TEXT;
130+
nestedStructure.text = ArrangerNestedObjectsTest.FIXED_TEXT;
131131
return nestedStructure;
132132
}
133133
}
@@ -148,7 +148,7 @@ class NestedStructure2Arranger extends CustomArranger<NestedStructure2> {
148148
@Override
149149
protected NestedStructure2 instance() {
150150
NestedStructure2 nestedStructure = enhancedRandom.nextObject(NestedStructure2.class);
151-
nestedStructure.text = ArrangerTestNestedObjects.FIXED_TEXT;
151+
nestedStructure.text = ArrangerNestedObjectsTest.FIXED_TEXT;
152152
return nestedStructure;
153153
}
154154
}

src/test/java/com/ocadotechnology/gembus/test/ArrangerTestOverrideDefaults.java renamed to src/test/java/com/ocadotechnology/gembus/test/ArrangerOverrideDefaultsTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
import static org.assertj.core.api.Assertions.assertThat;
2525

26-
public class ArrangerTestOverrideDefaults {
26+
public class ArrangerOverrideDefaultsTest {
2727

2828
@AfterEach
2929
public void cleanupProperties() {

src/test/java/com/ocadotechnology/gembus/test/ArrangerTestOverrides.java renamed to src/test/java/com/ocadotechnology/gembus/test/ArrangerOverridesTest.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
import static org.assertj.core.api.Assertions.assertThat;
2727
import static org.assertj.core.api.ThrowableAssert.catchThrowable;
2828

29-
public class ArrangerTestOverrides {
29+
public class ArrangerOverridesTest {
3030
HashMap<String, Supplier<?>> overrides = new HashMap<>();
3131

3232
@Test
@@ -89,7 +89,7 @@ void should_throwException_when_supplyingWrongTypeInOverrides() {
8989

9090
//then
9191
assertThat(actual).isInstanceOf(IllegalArgumentException.class)
92-
.hasMessage("Can not set java.lang.String field com.ocadotechnology.gembus.test.ArrangerTestOverrides$ToOverride.text to java.lang.Long");
92+
.hasMessage("Can not set java.lang.String field com.ocadotechnology.gembus.test.ArrangerOverridesTest$ToOverride.text to java.lang.Long");
9393
}
9494

9595
@Test
@@ -102,7 +102,7 @@ void should_throwException_when_supplyingOverrideForNonExistingField() {
102102

103103
//then
104104
assertThat(actual).isInstanceOf(IllegalArgumentException.class)
105-
.hasMessage("Failed to override field nonexisting in class com.ocadotechnology.gembus.test.ArrangerTestOverrides$ToOverride");
105+
.hasMessage("Failed to override field nonexisting in class com.ocadotechnology.gembus.test.ArrangerOverridesTest$ToOverride");
106106
}
107107

108108
@Test
@@ -162,7 +162,7 @@ void should_throwException_when_supplyingOverrideForNonExistingRecordField() {
162162

163163
//then
164164
assertThat(actual).isInstanceOf(IllegalArgumentException.class)
165-
.hasMessage("Failed to override field nonexisting in class com.ocadotechnology.gembus.test.ArrangerTestOverrides$RecordToOverride");
165+
.hasMessage("Failed to override field nonexisting in class com.ocadotechnology.gembus.test.ArrangerOverridesTest$RecordToOverride. Field not found.");
166166
}
167167

168168
@Test
@@ -175,7 +175,9 @@ void should_throwException_when_supplyingWrongTypeInOverridesForRecord() {
175175
Throwable actual = catchThrowable(() -> some(RecordToOverride.class, overrides));
176176

177177
//then
178-
assertThat(actual).isInstanceOf(ObjectCreationException.class);
178+
assertThat(actual)
179+
.isInstanceOf(IllegalArgumentException.class)
180+
.hasCauseInstanceOf(ObjectCreationException.class);
179181
}
180182

181183
static class ToOverride {

src/test/java/com/ocadotechnology/gembus/test/ArrangerRecordsTest.java

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@
2424
import java.util.Optional;
2525
import java.util.Set;
2626

27-
import static com.ocadotechnology.gembus.test.Arranger.some;
28-
import static com.ocadotechnology.gembus.test.Arranger.someSimplified;
27+
import static com.ocadotechnology.gembus.test.Arranger.*;
2928
import static org.assertj.core.api.Assertions.assertThat;
3029

3130
public class ArrangerRecordsTest {
@@ -105,7 +104,7 @@ void should_limitTheNestingLevel_when_inDirectlyRecursiveStructures() {
105104

106105
//then
107106
assertThat(actual.value()).isNotNull();
108-
assertThat(actual.child().child().child().child()).isEqualTo(new DirectlyNested(null,null));
107+
assertThat(actual.child().child().child().child()).isEqualTo(new DirectlyNested(null, null));
109108
assertThat(actual.child().child().value()).isNotNull();
110109
}
111110

@@ -120,9 +119,39 @@ void should_notRepeatTheSameValues_when_generatingRecords() {
120119
assertThat(actual1.surname()).isNotEqualTo(actual2.surname());
121120
assertThat(actual1.age()).isNotEqualTo(actual2.age());
122121
}
122+
123+
@Test
124+
void should_overridePrimitivesInRecords() {
125+
//given
126+
long expectedLong = someLong();
127+
int expectedInt = someInteger();
128+
129+
//when
130+
RecordWithPrimitive actual = some(RecordWithPrimitive.class, Map.of(
131+
"big", () -> expectedLong,
132+
"small", () -> expectedInt
133+
));
134+
135+
//then
136+
assertThat(actual.big()).isEqualTo(expectedLong);
137+
assertThat(actual.small()).isEqualTo(expectedInt);
138+
}
139+
140+
@Test
141+
void should_overrideObjectsInRecords() {
142+
//given
143+
int expectedValue = someInteger();
144+
145+
//when
146+
Data actual = some(Data.class, Map.of("value", () -> expectedValue));
147+
148+
//then
149+
assertThat(actual.value()).isEqualTo(expectedValue);
150+
}
123151
}
124152

125-
record PersonRecord(String name, String surname, Integer age) {}
153+
record PersonRecord(String name, String surname, Integer age) {
154+
}
126155

127156
record Data(Integer value, String name, Set<String> tags, List<NestedStructure> classWithCustomArranger) {
128157
Data {
@@ -159,4 +188,7 @@ protected Always42 instance() {
159188
}
160189

161190
record DirectlyNested(DirectlyNested child, Integer value) {
191+
}
192+
193+
record RecordWithPrimitive(long big, int small) {
162194
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/*
2+
* Copyright © 2020 Ocado (marian.jureczko@ocado.com)
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.ocadotechnology.gembus.test;
17+
18+
import static org.assertj.core.api.Assertions.assertThat;
19+
20+
import org.junit.jupiter.params.ParameterizedTest;
21+
import org.junit.jupiter.params.provider.Arguments;
22+
import org.junit.jupiter.params.provider.MethodSource;
23+
24+
import java.util.stream.Stream;
25+
26+
class ReflectionHelperTest {
27+
28+
@ParameterizedTest(name = "{3}")
29+
@MethodSource("allCases")
30+
void should_detectPrimitiveField(Class<?> clazz, String fieldName, boolean expected, String description) {
31+
//when
32+
boolean actual = ReflectionHelper.isPrimitiveField(clazz, fieldName);
33+
34+
//then
35+
assertThat(actual).isEqualTo(expected);
36+
}
37+
38+
static Stream<Arguments> allCases() {
39+
return Stream.of(
40+
Arguments.of(PlainClass.class, "primitive", true, "SHOULD detect primitive WHEN field is primitive in plain class"),
41+
Arguments.of(PlainClass.class, "boxed", false, "SHOULD detect non-primitive WHEN field is boxed in plain class"),
42+
Arguments.of(PlainRecord.class, "primitive", true, "SHOULD detect primitive WHEN field is primitive in record"),
43+
Arguments.of(PlainRecord.class, "boxed", false, "SHOULD detect non-primitive WHEN field is boxed in record"),
44+
Arguments.of(ChildWithPrimitiveParent.class, "primitive", true, "SHOULD detect primitive WHEN field is inherited from parent"),
45+
Arguments.of(ChildWithBoxedParent.class, "boxed", false, "SHOULD detect non-primitive WHEN field is inherited from parent"),
46+
Arguments.of(ChildHidesWithBoxed.class, "value", false, "SHOULD detect non-primitive WHEN child hides parent field"),
47+
Arguments.of(ChildHidesWithPrimitive.class, "value", true, "SHOULD detect primitive WHEN child hides parent field"),
48+
Arguments.of(PlainClass.class, "missing", false, "SHOULD return false WHEN field does not exist"),
49+
Arguments.of(PlainClass.class, "", false, "SHOULD return false WHEN field name is empty"),
50+
Arguments.of(PlainClass.class, null, false, "SHOULD return false WHEN field name is null")
51+
);
52+
}
53+
54+
static class PlainClass {
55+
int primitive;
56+
Integer boxed;
57+
}
58+
59+
record PlainRecord(int primitive, Integer boxed) {
60+
}
61+
62+
static class ParentWithPrimitive {
63+
int primitive;
64+
}
65+
66+
static class ChildWithPrimitiveParent extends ParentWithPrimitive {
67+
}
68+
69+
static class ParentWithBoxed {
70+
Integer boxed;
71+
}
72+
73+
static class ChildWithBoxedParent extends ParentWithBoxed {
74+
}
75+
76+
static class ParentPrimitiveValue {
77+
int value;
78+
}
79+
80+
static class ChildHidesWithBoxed extends ParentPrimitiveValue {
81+
String value;
82+
}
83+
84+
static class ParentBoxedValue {
85+
String value;
86+
}
87+
88+
static class ChildHidesWithPrimitive extends ParentBoxedValue {
89+
int value;
90+
}
91+
}

0 commit comments

Comments
 (0)