Skip to content

EasyTest : Understanding @Intercept annotation

anujgandharv edited this page Dec 29, 2012 · 4 revisions

There are many use cases in the Software Testing cycle where a user would like to do something before(or after)a method under test*(Difference b/w method under test and test method below) is executed. One use case is that you have your integration tests and you want to measure how much time a given method of your Service class is taking. You want to look at its performance to see if something is wrong with your service.

Another use case could be that you want to modify the output of your test method(EasyTest supports test methods that can return values) before it is captured by the EasyTest Framework.

And there would be some more. EasyTest provides an extremely simple way for the user to realize the above use cases. Using the @Intercept Annotation on the object instance that is under test.

Lets delve into an example.

@RunWith(DataDrivenTestRunner.class)
public class InterceptorTest {

@Intercept 
private RealItemService itemService = new RealItemService();

In the above example you have to note the following things:

  • We are using an annotation @Intercept that tells the EasyTest framework to intercept all the calls to the methods of the class instance represented by itemService field.
  • The field can have any modifier: public,private, protected or default.
  • The Class to intercept can be a concrete class or an interface. In case of concrete classes, CGLIB is used to create a dynamic proxy. In case of Interfaces, JDK dynamic proxy is used behind the scenes to proxy the class. All this is hidden from the end user using a single @Intercept annotation and EasyTest defined MethodInterceptor interface.

In the above case, what will happen is that if you have your debug log enabled then you will see a debug statement identifying how much time a particular method of a class took to run in nanoseconds. this is the default behavior. If you want to write your own interceptor, you can do that like this :

@RunWith(DataDrivenTestRunner.class)
public class InterceptorTest {

@Intercept(interceptor=MyInterceptor.class) 
private RealItemService itemService = new RealItemService();

In this case, EasyTest framework will register MyInterceptor with the proxy and everytime a method on itemService is called, your MyInterceptor will be invoked.

You can write your own interceptor by implementing the EasyTest provided MethodIntercepterinterface. This interface essentially hides the actual implementation details from the end user. Thus, a user doesnt have to implement 2 diffierent interfaces as provided by JDK Proxy and CGLIB proxy implementations.

Using @Intercept annotation with easytest-spring project

In case you are using easytest's spring module (easytest-spring) you can use the same @Intercept annotation when you are running your test cases using SpringTestRunner. The difference when using the @Intercept annotation with SpringTestRunner is that the implementation used behind the scene is that provided by Spring-aop. This is to keep it consistent with Spring AOP and Spring in general as Spring also applies other AOP and using Spring-aop gaurantees that our AOP will also be applied at the right location.

 @RunWith(SpringTestRunner.class)
 @ContextConfiguration(classes = { XmlBusinessConfig.class }, loader =   AnnotationConfigContextLoader.class)
 @DataLoader(filePaths = { "classpath:input-data.xml" }, loaderType = LoaderType.XML)
  @TransactionConfiguration(transactionManager="transactionManager" )
  @Transactional
   public class TestSpringConfiguration {

     @Autowired
     @Intercept
     public ItemService testSubject;