Skip to content

Commit

Permalink
Fail the randomization process if a setter invocation fails
Browse files Browse the repository at this point in the history
Before this commit, if the invocation of a setter fails,
Easy Random will set the field via reflection. This means
Easy Random might not respect the behaviour that the class
designer has intended and can generate invalid random instances.

This commit makes Easy Random fail by default in such cases.

Resolves #400
  • Loading branch information
fmbenhassine committed Mar 25, 2020
1 parent 2b1c421 commit 64d9570
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.jeasy.random.randomizers.misc.SkipRandomizer;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Type;

import static org.jeasy.random.util.CollectionUtils.randomElementOf;
Expand Down Expand Up @@ -90,7 +91,13 @@ void populateField(final Object target, final Field field, final RandomizationCo
throw new ObjectCreationException(exceptionMessage, e);
}
}
setProperty(target, field, value);
try {
setProperty(target, field, value);
} catch (InvocationTargetException e) {
String exceptionMessage = String.format("Unable to invoke setter for field %s of class %s",
field.getName(), target.getClass().getName());
throw new ObjectCreationException(exceptionMessage, e.getCause());
}
}
context.popStackItem();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ public static List<Field> getInheritedFields(Class<?> type) {
* @param value value to set
* @throws IllegalAccessException if the property cannot be set
*/
public static void setProperty(final Object object, final Field field, final Object value) throws IllegalAccessException {
public static void setProperty(final Object object, final Field field, final Object value) throws IllegalAccessException, InvocationTargetException {
try {
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), object.getClass());
Method setter = propertyDescriptor.getWriteMethod();
Expand All @@ -137,7 +137,7 @@ public static void setProperty(final Object object, final Field field, final Obj
} else {
setFieldValue(object, field, value);
}
} catch (IntrospectionException | InvocationTargetException | IllegalAccessException e) {
} catch (IntrospectionException | IllegalAccessException e) {
setFieldValue(object, field, value);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,23 @@ void generatedBeansShouldBeCorrectlyPopulated() {
validatePerson(person);
}

@Test
void shouldFailIfSetterInvocationFails() {
EasyRandom easyRandom = new EasyRandom();
Throwable thrown = catchThrowable(() -> easyRandom.nextObject(Salary.class));

assertThat(thrown).isInstanceOf(ObjectCreationException.class)
.hasMessageContaining("Unable to create a random instance of type class org.jeasy.random.beans.Salary");

Throwable cause = thrown.getCause();
assertThat(cause).isInstanceOf(ObjectCreationException.class)
.hasMessageContaining("Unable to invoke setter for field amount of class org.jeasy.random.beans.Salary");

Throwable rootCause = cause.getCause();
assertThat(rootCause).isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("Amount must be positive");
}

@Test
void finalFieldsShouldBePopulated() {
Person person = easyRandom.nextObject(Person.class);
Expand Down
40 changes: 40 additions & 0 deletions easy-random-core/src/test/java/org/jeasy/random/beans/Salary.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* The MIT License
*
* Copyright (c) 2020, Mahmoud Ben Hassine (mahmoud.benhassine@icloud.com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.jeasy.random.beans;

public class Salary {

private int amount;

public int getAmount() {
return amount;
}

public void setAmount(int amount) {
if (amount <= 0) {
throw new IllegalArgumentException("Amount must be positive");
}
this.amount = amount;
}
}

0 comments on commit 64d9570

Please sign in to comment.