Anton Hlinisty
Anton Hlinisty

Reputation: 1467

Spock. How to mock java.lang.Class?

I have a class with field of type java.lang.Class:

Class clazz

That is then used in sevaral methods in the following manner:

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

The problem is that I encounter problems with mocking the java.lang.Class. I tried:

Mock(Class)

and got:

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.

but:

GroovyMock(Class)

gives:

java.lang.IllegalAccessError: java.lang.Class

Is there any proper way to mock Class to verify it's interactions?

Upvotes: 2

Views: 3047

Answers (2)

Gergely Toth
Gergely Toth

Reputation: 6977

One should not be doing this as I suspect that it can have some side effects, but to answer the question the following will work:

def dummyObject = new Object()

Class.metaClass.static.newInstance = { dummyObject }

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

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

Also note that Class.newInstance should be set to the original at the end

Upvotes: 2

Patrick Koorevaar
Patrick Koorevaar

Reputation: 1343

How about making a wrapper class around Class? You can then let the wrapper class implement an interface and then create a mock for that interface:

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();           
    }
}

Upvotes: 0

Related Questions