views:

226

answers:

2

I have a factory method that creates objects to be used in unit tests. These objects all derive from the same base class:

public static <T extends BaseEntity> T modMake(Class<T> clazz)
{
    try {
        return clazz.newInstance();
    } catch (InstantiationException e) {
        // Should never happen
        throw new AssertionError(e);
    } catch (IllegalAccessException e) {
        // Should never happen
        throw new AssertionError(e);
    }
}

Now I want to override a getter method from that base class, but just for the tests. I would usually do that with an anonymous class, for example (Node being one of the subtaypes of BaseEntity):

public static Node nodMake()
{
    return new Node() {
        @Override
        public long ixGet() { return 1; }
    };
}

Can I do that in the function using the Class argument, too?

A: 

I don't think there is any way to do that. You probably need to look into bytecode manipulators if you really need to go that route. Javassist and BCEL are a couple of choices.

Jonathan
+1  A: 

Lose your factory method and use a mocking API like EasyMock to achieve the behavior you describe.

Your code will then end up something like this:

long returnValue = 12;

Node nodeMock = createMock(Node.class);
expect(nodeMock.ixGet()).andReturn(returnValue);
replay(nodeMock);

//add test code here

verify(nodeMock);

To answer Hanno's question on how this works:

It depends on whether your mocking an interface or a class.

The case of the interface is simple (code-wise), it uses what's called a dynamic proxy, which is part of core Java.

In the case of the class it's doing the bytecode manipulation that @Jonathan mentions in his answer, just behind a nice API.

Both the above mechanisms allow the method calls to be intercepted and EasyMock simply responds based on the expectations you've setup.

Nick Holt
Interesting. I hadn't used Java like this, yet.
Hanno Fietz
I'm now actually using EasyMock and it rocks. Thanks!
Hanno Fietz