Mockito通过反射从泛型类型的构造函数参数创建模拟

时间:2015-10-13 22:04:24

标签: java unit-testing mockito

我正在尝试为单元测试创​​建一个基本抽象类。在C#中执行此操作非常容易,但在java中却无法实现。我的想法是,我将有一个TestFor类,它将用作单元测试的基础。 T代表被测试的类型。在这个类中,我想创建类型为T的对象及其最长构造函数MOCKED的所有参数。这意味着我必须反映类,获取最长的构造函数,拉出参数,创建此参数的模拟,然后创建类型为T的对象。我有以下代码但不工作。任何可以尝试的人

public abstract class TestFor<T> {

protected Class<T> _class = null;
public HashMap<Class, Class<?>> _mocks = new HashMap<Class, Class<?>>();
protected T Target = null;

protected TestFor(Class<T> cls) {
    _class = cls;

    Constructor<T>[] allConstructors = (Constructor<T>[]) _class.getDeclaredConstructors();

    Constructor<T> ctorWithLongestParameter = null;
    int max = 0;
    for (Constructor ctor : allConstructors) {
        if (ctor.getParameterTypes().length > max) {
            ctorWithLongestParameter = ctor;
            max = ctor.getParameterTypes().length;
        }
    }

    final List<Object> objects = new ArrayList<Object>();
    int i = 0;
    for (Class<?> p : ctorWithLongestParameter.getParameterTypes()) {
        Class<?> mock = Mockito.mock(p.getClass()); //This does not work
        _mocks.put(p.getClass(), mock);
        objects.add(mock);
    }
    try {
        Target = (T) ctorWithLongestParameter.newInstance(objects);
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }
}

public <E> E the(Class clss) {
    return (E) _mocks.get(clss);
}

}

1 个答案:

答案 0 :(得分:1)

您的代码中存在多个错误 - 逻辑,类型,泛型......请尝试以下方法:

public abstract class TestFor<T> {

    protected Class<T> _class = null;
    public Map<Class, Object> _mocks = new HashMap<>();
    protected T Target = null;

    protected TestFor(Class<T> cls) {
        _class = cls;

        List<Constructor> allConstructors = Arrays.asList(_class.getDeclaredConstructors());
        Constructor ctorWithLongestParameter = Collections.max(allConstructors,
            (o1, o2) -> Integer.compare(o1.getParameterCount(), o2.getParameterCount()));

        List<Object> objects = new ArrayList<>();
        int i = 0;
        for (Class<?> type : ctorWithLongestParameter.getParameterTypes()) {
            Object mock = _mocks.get(type);
            if (mock == null) {
                mock = Mockito.mock(type);
                _mocks.put(type, mock);
            }
            objects.add(mock);
        }
        try {
            Target = _class.cast(ctorWithLongestParameter.newInstance(objects.toArray(new Object[objects.size()])));
        } catch (ReflectiveOperationException e) {
            throw new RuntimeException(e);
        }
    }

    public <E> E the(Class<E> cls) {
        return cls.cast(_mocks.get(cls));
    }

    public static void main(String[] args) {
        TestFor<A> test = new TestFor<A>(A.class) {};
        System.out.println(test.Target);
        System.out.println(test.the(Object.class));
        System.out.println(test.the(Number.class));
    }

    public static class A {
        public A() {
            System.out.println("Empty constructor");
        }
        public A(Object o) {
            System.out.println("Constructor [o=" + o + ']');
        }
        public A(Object o, Number n) {
            System.out.println("Constructor [o=" + o + ", n=" + n + ']');
        }
    }
}

此代码适用于Java 8,但经过小幅修改后,它将适用于旧版本。