SurrogateCalls.java :  » Testing » Surrogate » net » sf » surrogate » core » Java Open Source

Java Open Source » Testing » Surrogate 
Surrogate » net » sf » surrogate » core » SurrogateCalls.java
/* Copyright (c) 2005 Per S Hustad. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 *
 *  o Redistributions of source code must retain the above copyright notice, 
 *    this list of conditions and the following disclaimer. 
 *    
 *  o Redistributions in binary form must reproduce the above copyright notice, 
 *    this list of conditions and the following disclaimer in the documentation 
 *    and/or other materials provided with the distribution. 
 *    
 *  o Neither the name of surrogate.sourceforge.net nor the names of 
 *    its contributors may be used to endorse or promote products derived 
 *    from this software without specific prior written permission. 
 *    
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package net.sf.surrogate.core;

import net.sf.surrogate.core.SurrogateManager;
/**
 * Abstract aspect for use with the Surrogate framework. This aspect provides
 * the standard interaction with the
 * {@link net.sf.surrogate.core.SurrogateManager}. Instead of coding relatively
 * complex advices, the user only needs to create a concrete implementation of
 * the <code>SurrogateCalls</code> advice, and implement the <a
 * href=#mockPointcut()"> <code>mockPointcut</code> </a> pointcut. The advices
 * then handles the standard processing towards the
 * <code>SurrogateManager</code>.
 * <p>
 * An example implementation is
 * <pre>
 *     aspect MyCalls extends SurrogateCalls {
 *   
 *       protected pointcut mockPoincut() : 
 *         (
 *           execution(* com.mycompany.MyClass.getOrder(..) ) ||
 *           call (java.io.*Writer.new(..)) ||
 *           call(* java.lang.System.currentTimeMillis())
 *         ) ;
 *    }
 * </pre> 
 * and an example "difficult-to-test or mock" java class is:
 * <pre>
 *    package com.mycompany;
 *    import java.io.*;
 *  
 *    public class MyClass {
 *    
 *      public static final Order getOrder(String orderId) {
 *        Writer out = new BufferedWriter(
 *               new FileWriter(&quot;D:/production/customer_name.log&quot;));
 *        out.write(orderId);
 *        return new Order(System.currentTimeMillis());
 *      }
 *      ....
 *   }
 * </pre>
 * Since the method is final and contains calls to external, varying entities
 * (system time and external file), it is normally difficult to 1) replace the
 * "getOrder" method by a mock and 2) test the internals of the method.
 * Surrogate provides a solution to this problem.
 * 
 * The advice would, when woven with the "classes-under-test", allow you to
 * substitute mock objects for the following:
 * <ul>
 * <li>Every time <code>com.mycompany.MyClass.getOrder</code> executes. You
 * could override the method by a corresponding "mock method" using the
 * {@link net.sf.surrogate.core.SurrogateManager#addMockMethod addMockMethod},
 * or override the method execution and return value by using the
 * {@link net.sf.surrogate.core.SurrogateManager#addMock addMock} method.
 * <li>Every time a "Writer" in the "java.io" package is instantiated from
 * within the classes-under-test. You could override the BufferedWriter and/or
 * FileWriter with a custom-made mock Writer extending the class. The mock is
 * added using the
 * {@link net.sf.surrogate.core.SurrogateManager#addMock addMock} method.
 * <li>Every time the classes-under-test call
 * <code>System.currentTimeMillis()</code>. You could control the time
 * returned by using the
 * {@link net.sf.surrogate.core.SurrogateManager#addMockMethod addMockMethod}
 * </ul>
 * 
 * @author Per S Hustad
 */

public abstract aspect SurrogateCalls  {
   /**
    * Defines the pointcut allowing to substitute method return values with a
    * mock object implementation or to substitute a method call or method
    * execution with a <code>MockMethod</code>. Resulting implementations of
    * this pointcut must be <b>method </b> or </b>constructor </b> pointcuts.
    * <p>
    * <strong>Note: </strong> If you define a pointcut on a method returning,
    * say <code>java.lang.Object</code> be aware of that the return value
    * almost certainly will be subsituteted by any mock object, since all
    * Objects inherits from <code>java.lang.Object</code>.
    */
   protected abstract pointcut mockPointcut();
   
   
   /*
    * Tell the AspectJ weaver to fail with an error message if the subclasses
    * implements mockPointcuts which are not "call" or "execution". Otherwise, a
    * runtime exception would be thrown by the SurrogateManager
    */
   declare error : (mockPointcut() && 
       !(call(* *(..)) || execution(* *(..)) ||
         call(*.new(..)) || execution(*.new(..))    
       ))
       : 
    "surrogate: \"mockPointcuts\" must be \"call\" or \"execution\" pointcuts";


   /**
    * Executes when a <code>mockPointcut</code> pointcut is detected. If a
    * mock has been registered, that object is allowed to execute, otherwise,
    * the original code is allowed to proceed.
    * <p>
    * <b>Throws </b> Throwable - any Throwable thrown by the SurrogateManager or
    * executing mock is catched and rethrown.
    * <p>
    * <b>See also </b><a
    * href="SurrogateManager.html#getMockExecutor">SurrogateManager.getMockExecutor
    * </a> <b><a href="ExceptionThrower.html">ExceptionThrower </a> <b>
    */
    Object around() : mockPointcut()
    { 
      try
      {
        SurrogateManager.MockExecutor e = 
            SurrogateManager.getInstance().getMockExecutor(thisJoinPoint);
        return e != null ? e.execute(thisJoinPoint.getArgs()) : proceed();
      } catch (Throwable t) {
        ExceptionThrower.throwThrowable(t);
        return null;
      }
    } 
    
 }
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.