5

我正在寻找一些实用程序类/代码,它们将采用 java bean 并将其所有值初始化为随机值。它可以通过反射来完成,因为一些库已经创建了 toString() 或 equals() 方法。例如,在开发 UI 以获取一些数据时很有用。

其他可能的好东西:

  1. 也递归地初始化非原始或简单(字符串,日期)成员
  2. 初始化 bean 的集合
  3. 也许给一些方法来限制生成的值,例如我们可以给出范围的数字,字符串正则表达式或通配符......

有人知道这样的事情吗?谢谢

编辑:解决...让 Apocalisp 的样本正常工作,这绝对是我想要的。恕我直言,它有一些缺点:

  • 该库的范围比该用途大得多,但这对我来说不是问题
  • 除非您花一些时间来研究整个事物,否则要了解如何为您的对象构建 Arbitrary 是相当复杂的。这是一个缺点。
  • 我猜它可能更简洁,但这也很好。

谢谢!

4

6 回答 6

8

看看 Easy Random:https ://github.com/j-easy/easy-random 。

它允许您使用随机数据填充 Java 对象图。

免责声明:我是该库的作者

于 2016-04-19T18:59:34.930 回答
2

虽然我确实注意到这篇文章可能有点老了,但我只是碰巧有同样的必要性,而且所提出的解决方案似乎都不能很好地解决它,所以我做了一些快速而肮脏的 15 分钟不完全- 用于生成随机填充 bean 的通用实用程序方法,这对于碰巧遇到类似问题的其他人可能有用也可能没有用:

import java.beans.PropertyDescriptor;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.Random;

import org.springframework.beans.BeanUtils;

public class RandomBeanUtil {

    public static <T> Collection<T> generateTestData(Class<T> clazz, int quantity) {
        Collection<T> list = new ArrayList<T>();

        PropertyDescriptor[] descriptors = BeanUtils.getPropertyDescriptors(clazz);
        Random rand = new Random();

        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.HOUR, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);

        try {
            for (int i = 0; i != quantity; i++) {
                    T o = clazz.newInstance();

                    for (PropertyDescriptor descriptor : descriptors) {
                        Class<?> type = descriptor.getPropertyType();
                        if (String.class.isAssignableFrom(type)) {
                            descriptor.getWriteMethod().invoke(o, String.valueOf(new char[]{
                                    (char)('A' + rand.nextInt(26)), (char)('a' + rand.nextInt(26)) }));
                        } else if (Date.class.isAssignableFrom(type)) {
                            cal.add(Calendar.DATE, rand.nextInt(60) - 30);
                            descriptor.getWriteMethod().invoke(o, cal.getTime());
                        } else if (BigDecimal.class.isAssignableFrom(type)) {
                            descriptor.getWriteMethod().invoke(o, 
                                    new BigDecimal(rand.nextDouble() * 500).setScale(2, RoundingMode.HALF_UP));
                        }
                    }

                    list.add(o);
            }       
        } catch (Exception e) {
            // TODO: Improve exception handling
            throw new RuntimeException("Error while generating the bean collection", e);
        }

        return list;
    }

}
于 2012-02-09T16:10:54.027 回答
1

看看Reductio 库中的 Gen 类。这是用于生成或多或少任何类型的任意值的高度可配置框架的一部分。提供了原始类型和大多数 Java 集合类的生成器。您应该能够Arbitrary相当轻松地为您的类创建实例。

编辑这是示例,已更正:

import static fj.test.Arbitrary.*;
import static fj.Function.*;

static final Arbitrary<Person> personArbitrary =
  arbitrary(arbInteger.gen.bind(arbString.gen, arbBoolean.gen,
      curry(new F3<Integer, String, Boolean, Person>() {
        public Person f(final Integer age, final String name, final Boolean male)
          {return new Person(age, name, male);}})));

然后像这样生成一个“大小 100”的任意人。即,它的名称最多为 100 个字符。

Person p = personArbitrary.gen.gen(100, Rand.standard);
于 2009-05-15T13:20:09.357 回答
0

我没有适合你的库,但如果你有一个随机生成器,那么这个类可能会派上用场:

public class BeanMethodIterator implements Iterable<Method> {

    private static final int MODIFIER_FILTER = (Modifier.PUBLIC | Modifier.STATIC);
    private static final int MODIFIER_EXPECTED = Modifier.PUBLIC;

    /**
     * Indicator to filter getter or setter methods. 
     */
    public enum Filter {

        /** Only getter methods. */
        GETTERS(new Transform<Method, Boolean>(){
            public Boolean transform(Method input) {
                return (input.getName().startsWith("get") || 
                        input.getName().startsWith("is")) 
                    &&  input.getParameterTypes().length == 0;
            };
        }),

        /** Only setter methods. */
        SETTTERS(new Transform<Method, Boolean>(){
            public Boolean transform(Method input) {
                return input.getName().startsWith("set") && 
                    input.getParameterTypes().length == 1;
            };
        }),

        /** Getter and setter methods. */
        BOTH(new Transform<Method, Boolean>(){
            public Boolean transform(Method input) {
                return Filter.SETTTERS.condition.transform(input) || 
                    Filter.GETTERS.condition.transform(input);
            };
        });

        private Transform<Method, Boolean> condition;

        private Filter(Transform<Method, Boolean> condition) {
            this.condition = condition;
        }

    };

    /**
     * Iterate parent methods also?
     */
    public enum Scope {
        PARENTS_ALSO() {
            @Override
            protected Method[] getMethods(Class<?> c) {
                return c.getMethods();
            };
        },
        THIS_CLASS_ONLY() {
            @Override
            protected Method[] getMethods(Class<?> c) {
                return c.getDeclaredMethods();
            }
        };

        protected abstract Method[] getMethods(Class<?> c);
    }

    private final Filter filter;
    private final Scope scope;
    private final Class<?> theClass;

    /**
     * Constructor. 
     *
     * @param theClass
     * @param what
     */
    public BeanMethodIterator(Class<?> theClass, Filter what, Scope scope) {
        this.filter = what;
        this.theClass = theClass;
        this.scope = scope;
    }

    /**
     * Constructor. 
     */
    public BeanMethodIterator(Class<?> theClass) {
        this(theClass, Filter.BOTH, Scope.PARENTS_ALSO);
    }

    /**
     * Tells if a method is public
     * @param method
     * @return
     */
    private static boolean isPublic(Method method) {
        return (method.getModifiers() & MODIFIER_FILTER) == MODIFIER_EXPECTED; 
    }

    /**
     * {@inheritDoc}
     * @see java.lang.Iterable#iterator()
     */
    public Iterator<Method> iterator() {
        final Method[] methods = this.scope.getMethods(this.theClass);        

        return new Iterator<Method>() {
            int index = 0;

            public boolean hasNext() {
                while (index < methods.length) {
                    if (isPublic(methods[index]) && filter.condition.transform(methods[index]))
                        return true;
                    index++;
                }
                return false;
            }

            public Method next() {
                if (!hasNext())
                    throw new NoSuchElementException();
                return methods[index++];
            }

            public void remove() {
                throw new UnsupportedOperationException();
            }

        };
    }

    public static void main(String[] args) {
        for (Method m: new BeanMethodIterator(Date.class, Filter.GETTERS, Scope.THIS_CLASS_ONLY)) {
            System.out.println(m.getName());
        }
    }

}


/**
 * Represents a function that takes one input and returns a transformation of that input value i.e.
 * a transformation. The name Transform is used because it is shorter.
 * 
 * @author Hannes de Jager
 * @since 01 Sep 2008
 */
interface Transform<I, O> {

    /**
     * Invokes the function, performing the transformation, to produce an interpreted value.
     * 
     * @param input the input value.
     * @return The computed result.
     */
    public O transform(I input);
}
于 2009-05-15T13:04:05.497 回答
0

Apache Commons BeanUtils (http://commons.apache.org/beanutils)可能对你有用。没有任何可以开箱即用的实用程序,但我想所有的构建块都在那里,即访问属性、随机生成器。

于 2009-05-15T13:34:22.350 回答
0

您可以使用InPUT开源库做您想做的事情。它使用基于 XML 描述符的范围定义,而不是代码内定义。InPUT 使用方法和构造函数注入,支持任意初始化深度的复杂对象结构。示例教程可用。

于 2013-05-26T20:02:32.890 回答