Fill primitive properties with random data automatically?

JavaTesting

Java Problem Overview


Is there a java library that would help with creating instances of classes for testing? One that examines the properties of a bean and fills it with random data.
I'm basically looking for Java equivalent of Object Hydrator for C#.

Java Solutions


Solution 1 - Java

You could use PoDaM:

PodamFactory factory = new PodamFactoryImpl();
Pojo myPojo = factory.manufacturePojo(Pojo.class);

Solution 2 - Java

Take a look at Easy Random.

It allows you to populate a Java Object graph with random data.

Hope it helps.

Solution 3 - Java

I don't know of a framework, but it's pretty simple to write one of those yourself. The complexity comes in non-simple properties, aka object associations. Something like this handles the basics and then some:

public static void randomlyPopulateFields(Object object) {
    new RandomValueFieldPopulator().populate(object);
}

public static class RandomValueFieldPopulator {
    public void populate(Object object) {
        ReflectionUtils.doWithFields(object.getClass(), new RandomValueFieldSetterCallback(object));
    }

    private static class RandomValueFieldSetterCallback implements FieldCallback {
        private Object targetObject;

        public RandomValueFieldSetterCallback(Object targetObject) {
            this.targetObject = targetObject;
        }

        @Override
        public void doWith(Field field) throws IllegalAccessException {
            Class<?> fieldType = field.getType();
            if (!Modifier.isFinal(field.getModifiers())) {
                Object value = generateRandomValue(fieldType, new WarnOnCantGenerateValueHandler(field));
                if (!value.equals(UNGENERATED_VALUE_MARKER)) {
                    ReflectionUtils.makeAccessible(field);
                    field.set(targetObject, value);
                }
            }
        }
    }
}

public static Object generateRandomValue(Class<?> fieldType, CantGenerateValueHandler cantGenerateValueHandler) {
    if (fieldType.equals(String.class)) {
        return UUID.randomUUID().toString();
    } else if (Date.class.isAssignableFrom(fieldType)) {
        return new Date(System.currentTimeMillis() - random.nextInt(DATE_WINDOW_MILLIS));
    } else if (Number.class.isAssignableFrom(fieldType)) {
        return random.nextInt(Byte.MAX_VALUE) + 1;
    } else if (fieldType.equals(Integer.TYPE)) {
        return random.nextInt();
    } else if (fieldType.equals(Long.TYPE)) {
        return random.nextInt();
    } else if (Enum.class.isAssignableFrom(fieldType)) {
        Object[] enumValues = fieldType.getEnumConstants();
        return enumValues[random.nextInt(enumValues.length)];
    } else {
        return cantGenerateValueHandler.handle();
    }
}

Solution 4 - Java

https://github.com/benas/random-beans did the work for me, while PoDam failed with "fluent" setters and answer by Ryan Stewart is not complete for copy-paste as has references to classes that are not exposed! With random-beans it's as easy as:

Auction auction = EnhancedRandom.random(Auction.class);

Gradle:

testCompile ('io.github.benas:random-beans:3.4.0')

Solution 5 - Java

You can checkout randomizer for random data generation.This library helps to create random data from given Model class.Checkout below example code.

public class Person {
    
   @FirstName
   String mFirstName;
    
   @LastName
   String mLastName;
   
   @Number(min = 14,max = 25,decimals = 0)
   int age;
	
   @DateValue( from = "01 Jan 1990",to = "31 Dec 2002" , customFormat = "dd MMM yyyy")
   String dateOfBirth;
    
   @Email
   String  mEmailId;
   
   @StreetAddress
   public String streetAddress;

   @State
   public String state;
   
   //Person can have minimum 1 Phone number and maximum 3 phone number
   @Phone(country = Phone.Country.INDIA)
   @CollectionDescriptor(min = 1,max = 3) 
   List<String> phones;
  
}
    
//Generate random 100 Person(Model Class) object 
Generator<Person> generator = new Generator<>(Person.class);  
List<Person> persons = generator.generate(100);                          

As there are many built in data generator is accessible using annotation,You also can build custom data generator.I suggest you to go through documentation provided on library page.

Solution 6 - Java

For testing, our group has had some success with JUnit and Mockito. Here is a link to a Mockito answer.

I am not sure if filling with random data will be a meaningful test. Perhaps a more meaningful test would be testing normal, boundary, and error conditions.

Solution 7 - Java

I Have used reflection and recursion here to get all fields populated in my robust object that i wanted to get tested. This is Using PODAM as well i hope somebody will find this useful.

public class Populate {

    private final PodamFactory podamFactory = new PodamFactoryImpl();

    private <P> P getManufacturedPojo(final Class<P> klass) {
        return podamFactory.manufacturePojo(klass);
    }

    private Object populateAllIn(final Class targetClass) throws IllegalAccessException, InstantiationException {
        final Object target = targetClass.newInstance();

        //Get all fields present on the target class
        final Set<Field> allFields = getAllFields(targetClass, Predicates.<Field>alwaysTrue());

        //Iterate through fields
        for (final Field field : allFields) {

            //Set fields to be accessible even when private
            field.setAccessible(true);

            final Class<?> fieldType = field.getType();
            if (fieldType.isEnum() && EnrichmentType.class.isAssignableFrom(fieldType)) {
                 //handle any enums here if you have any
            }              

            //Check if the field is a collection
            if (Collection.class.isAssignableFrom(fieldType)) {

                //Get the generic type class of the collection
                final Class<?> genericClass = getGenericClass(field);

                //Check if the generic type of a list is abstract
                if (Modifier.isAbstract(genericClass.getModifiers())) {

                    //You might want to use any class that extends
                    //Your abstract class like 

                    final List<Object> list = new ArrayList<>();
                    list.add(populateAllIn(ClassExtendingAbstract.class));
                    field.set(target, list);

                } else {
                    final List<Object> list = new ArrayList<>();
                    list.add(populateAllIn(genericClass));
                    field.set(target, list);
                }

            } else if ((isSimpleType(fieldType) || isSimplePrimitiveWrapperType(fieldType)) && !fieldType.isEnum()) {
                field.set(target, getManufacturedPojo(fieldType));

            } else if (!fieldType.isEnum()) {
                field.set(target, populateAllIn(fieldType));
            }
        }
        return target;
    }

And some helper methods. Code might not be perfect but works :).

private Class<?> getGenericClass(final Field field) {
    final ParameterizedType collectionType = (ParameterizedType) field.getGenericType();
    return (Class<?>) collectionType.getActualTypeArguments()[0];
}

private boolean isSimpleType(final Class<?> fieldType) {
    return fieldType.isPrimitive()
            || fieldType.isEnum()
            || String.class.isAssignableFrom(fieldType)
            || Date.class.isAssignableFrom(fieldType);
}

private boolean isSimplePrimitiveWrapperType(final Class<?> fieldType) {
    return Integer.class.isAssignableFrom(fieldType)
            || Boolean.class.isAssignableFrom(fieldType)
            || Character.class.isAssignableFrom(fieldType)
            || Long.class.isAssignableFrom(fieldType)
            || Short.class.isAssignableFrom(fieldType)
            || Double.class.isAssignableFrom(fieldType)
            || Float.class.isAssignableFrom(fieldType)
            || Byte.class.isAssignableFrom(fieldType);
}

Thanks, and if there a easier way to populate everything please let me know.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionprasopesView Question on Stackoverflow
Solution 1 - Javapk1View Answer on Stackoverflow
Solution 2 - JavaMahmoud Ben HassineView Answer on Stackoverflow
Solution 3 - JavaRyan StewartView Answer on Stackoverflow
Solution 4 - JavaJuri ReinsaluView Answer on Stackoverflow
Solution 5 - JavaRonak PoriyaView Answer on Stackoverflow
Solution 6 - Javarajah9View Answer on Stackoverflow
Solution 7 - JavaLazerBananaView Answer on Stackoverflow