5.12.11

Testing EJB Interceptor with EasyMock

As stated in another post, some people might argue that Interceptors are difficult to test. For that reason I created a short example using EasyMock.
Imagine we have one EJB which connects to a webservice.Before each method invocation, we want to refresh the URL, as it might have changed, due to whatever reason. We could of course, create a private method which can be called whenever another method wants to make a webservice call. But we want to ensure that the URL is refreshed, so we use an Interceptor to get absolutely sure.

First our EJB, nothing special: 

@Stateless
@Interceptors(MyInterceptor.class)
public class SomeEJB implements SomeEJBLocal, URLparameterizable{
    private String url;
    public void doSmg(){
        //connect to webserivce
    }
    public void setWebserviceURL(String url) {
        this.url = url;
    }
}


After that we create our Interceptor, which uses just the URLparameterizable Interface

public class MyInterceptor {
    @AroundInvoke
    public Object invoke(InvocationContext ctx) throws Exception {
        URLparameterizable connectable = 

                     (URLparameterizable) ctx.getTarget();
        connectable.setWebserviceURL("http://webserviceMock");
        return ctx.proceed();
    }
}


The next step is to create our test. What we actually want to test is the invocation of the connectable object, which is retrieved using the InvocationContext. Of course, we could also create a Stub for the context, but in this case we are more interested in the behavior, than the state - if the method gets called properly- so a mock is sufficient. All in all, it is just important to create Test Double, as we want a unit and no integration test.

import org.junit.Test;
import static org.easymock.EasyMock.*;
import javax.interceptor.InvocationContext;

public class InterceptorTest {
    @Test
    public void verifyInterceptorInvocation() throws Exception {
        InvocationContext icxMock = 

                         createMock(InvocationContext.class);
        expect(icxMock.getTarget()).andReturn(new SomeEJB());
        expect(icxMock.proceed()).andReturn(new Object());
        replay(icxMock);
        MyInterceptor interceptor = new MyInterceptor();
        interceptor.invoke(icxMock);
        verify(icxMock);
    }

}



First,  the mock object for the InvocationContext is created. Furthermore, we define what we actually expect, when these two methods are called within the Interceptor class. After that, when the behaviour definition part is finished, replay() must be called. Last, after executing our method under test, verify() is called to check if the mock's methods were executed.
Next, we could add another test that verifies the behavior of the Interceptor if not a SomeEJB instance, but some other Object is returned.

Further readings:
http://martinfowler.com/articles/mocksArentStubs.html
http://easymock.org/EasyMock3_0_Documentation.html
http://xunitpatterns.com/

1 comment: