斯波克。如何模拟java.lang.Class?

Spock. How to mock java.lang.Class?

我有一个 class 字段类型 java.lang.Class:

Class clazz

然后按以下方式在多种方法中使用:

Object profile = objectDAO.get(clazz, id)
...
clazz.newInstance()

问题是我在模拟 java.lang.Class 时遇到问题。我试过了:

Mock(Class)

并得到:

org.spockframework.mock.CannotCreateMockException: Cannot create mock for class java.lang.Class because Java mocks cannot mock final classes. If the code under test is written in Groovy, use a Groovy mock.

但是:

GroovyMock(Class)

给出:

java.lang.IllegalAccessError: java.lang.Class

是否有任何适当的方法来模拟 Class 以验证其交互?

围绕 Class 制作包装器 class 怎么样?然后,您可以让包装器 class 实现一个接口,然后为该接口创建一个模拟:

public interface ClassWrapper {
    Class<?> getClazz();
    Object newInstance() throws InstantiationException, IllegalAccessException;
}

public class ClassWrapperImpl implements ClassWrapper {
    private Class<?> clazz;

    public ClassWrapperImpl(Class<?> clazz) {
        this.clazz = clazz;
    }

    @Override
    public Class getClazz() {
        return this.clazz;
    }

    @Override
    public Object newInstance() throws InstantiationException, IllegalAccessException {
        return this.clazz.newInstance();
    }

    // add more methods of the Class class that needs to be wrapped
}

public class SomeClass {
    private ClassWrapper cw;

    void methodA(Class<?> clazz) {
        cw = new ClassWrapperImpl(clazz); // (or better use dependency injection)
    }

    void methodB() {        
        Object profile = objectDAO.get(cw.getClazz(), id);          
        cw.newInstance();           
    }
}

不应该这样做,因为我怀疑它可能会产生一些副作用,但要回答这个问题,以下方法会起作用:

def dummyObject = new Object()

Class.metaClass.static.newInstance = { dummyObject }

def clazz = String
assert clazz.newInstance() == dummyObject

clazz = Integer
assert clazz.newInstance() == dummyObject

还要注意Class.newInstance最后要设置成原来的