sixlegs.com / blog / java / concrete-mock-objects.html

Root Beer Logo Root Beer

Chris Nokleberg's Fizzy Weblog

October 2003
Su M Tu W Th F Sa
      1 2 3 4
6 7 8 9 10 11
12 13 14 15 17 18
19 20 21 22 23 24 25
26 27 29 30 31
Previous  |  Next  |  More...
#  Mocking made easier

In Rickard's recent entry he discusses a technique whereby abstract classes can implement an arbitrary set of interfaces, the missing implementations of which are "filled in" by his AOP framework.

I've done something very similar with CGLIB for my own Mock Object needs. Let's say you need a mock HttpServletRequest. Actually implementing one is pain, since it has so many methods and you probably only care about one or two for a given test, for example:

abstract public class MockRequest implements HttpServletRequest {
    public String getRequestURI() {
        return "/foo";
    }
}

The trick is how to get an instance of MockRequest (you cannot instantiate one directly since it is abstract):

request = (HttpServletRequest)makeMock(MockRequest.class);

Here is the code for makeMock (using CGLIB2):

public static Object makeMock(Class impl) {
    return Enhancer.create(impl, null, NoOp.INSTANCE);
}

The CGLIB Enhancer API generates a dynamic subclass and implements all of the missing interface methods. Any method that you do not implement will simply throw an AbstractMethodError when called.

The advantage of using CGLIB here instead of Dynamic Proxies (besides performance) is that you are not limited to interfaces--you can just as easily create a mock for any class:

abstract public class MockImage extends java.awt.Image {
    public int getHeight(java.awt.ImageObserver observer) {
        return 480;
    }
    public int getWidth(java.awt.ImageObserver observer) {
        return 640;
    }
}

[Powered By FreeMarker]  [Valid Atom 1.0]  [Weblog Commenting by HaloScan.com]